Бывает, что нужно отладить программу, а GDB при этом недоступен. Например, потому что программу вы отлаживаете под MacOS или FreeBSD , а в этих системах традиционно используется отладчик LLDB. Лично я в последнее время склонен отдавать предпочтение LLVM-стэку (CLang, LLDB) даже на Linux-машинах, где по дэфолту используется GNU-стэк (GCC, GDB). В LLDB все еще есть кое-какие шероховатости. Но команды структурированы намного лучше, чем в GDB, а шероховатости со временем все равно поправят. Так или иначе, в процессе изучения LLDB я составил шпаргалку по основным его командам, которой и хочу сегодня с вами поделиться.
Важно! LLDB и вообще LLVM-стэк является сравнительно молодым проектом. Желательно использовать последнюю его версию, так как в новых релизах исправляют существенное количество багов и недоработок . Во FreeBSD последнюю версию LLDB можно установить из портов. О том, как установить последний LLVM / CLang / LLDB в Ubuntu Linux, ранее рассказывалось в заметке Определение степени покрытия кода на C/C++ тестами .
Примечание: Хоть ниже часто приводятся полные версии команд, можно использовать и короткие, например fr v
вместо frame variables
. Также все команды автодополняются при нажатии Tab.
Подрубиться к процессу:
На момент написания этих строк в LLDB был неприятный баг . Под FreeBSD, если программа использовала вызов setproctitle ( )
, к ней не удастся подключиться. Эту проблему при желании можно обойти. Например, если вы пилите что-то для PostgreSQL, то для определения pid бэкенда можно использовать запрос SELECT pg_backend_pid ( ) ;
(а еще удобнее прописать set PROMPT1 '%p =# '
в ~/.psqlrc) и компилировать PostgreSQL примерно так:
echo ‘#undef HAVE_SETPROCTITLE’ >> . / src / include / pg_config.h
Запуск программы с заданными аргументами:
Анализ корки:
Удаленная отладка. У меня лично не удалось ею воспользоваться на двух виртуалках с FreeBSD, происходила ошибка Process 1 exited with status = -1 (0xffffffff) lost connection
. Но в теории делается так.
На сервере в bash выполняем команду:
На клиенте запускаем LLDB без аргументов в нем:
platform select remote-freebsd
platform connect connect://192.168.122.184:1234
На сервере должны увидеть:
Теперь в LLDB на клиенте можно сказать:
platform process launch -c pwd
Просмотр справки:
help process
help process save-core
Выйти из отладчика (не прибивает процесс, как и в GDB):
Создать корку из отладчика:
Начать выполнение программы, если она еще не выполняется:
r (аргументы)
Продолжить выполнение программы:
process continue
Прервать выполнение программы:
Посмотреть исходный код:
list main.c:123
source list -f heapam.c -l 3050 -c 20
Когда исходников под рукой нет, можно посмотреть ассемблерный код:
disassemble —name main
disassemble —start-address 0x1a2b3c —end-address 0x4d5e6f
Чтение и запись регистров:
register read —all
register read rcx
register write al 0xCC
Step — шаг вперед или несколько шагов вперед:
s -c 10
Next — как step, только без захода внутрь других методов и процедур:
n -c 10
Until — выполнить программу до указанной строчки:
Продолжить выполнение до возвращения из текущей процедуры:
Посмотреть стэктрейс:
Перемещение между фреймами стака:
fr s 1
Информация о текущем фрейме:
Показать аргументы и переменные в текущем фрейме:
Показать только локальные переменные, без аргументов:
Показать только аргументы, без локальных переменных:
Ставим бряк:
b proc_name
Список бряков:
Удаление бряка по номеру:
Временное включение и выключение бряков:
breakpoint enable 1
Удаление всех бряков:
Вачпоинты — как бряки, только на обращение к памяти (заметьте, что одновременно можно создавать ограниченное количество вачпоинтов):
watchpoint list
watchpoint delete 1
Условные брейкпоинты ставятся как-то так (не забывайте взять условие в кавычки!):
b -f fasttab.c -l 679 —condition ‘result <= 0’
Заметьте, что b fname.c:123 --condition
не работает!
Список нитей:
Переключение на нитку:
Вывести значение переменных:
p my_struct->my_field
Можно менять значения переменных в программе:
Также можно кастовать типы:
Вообще, можно использовать отладчик, как калькулятор:
Чтение памяти:
me r —size 4 —format u —count 6 &event —outfile /tmp/1.txt
Запись в память:
Выполнение пачки операций:
Пример файла lldb.batch:
quit
По моему опыту, описанных выше команд хватает практически на все случаи жизни. Действительно не хватает разве что поддержки reverse debugging , которой на момент написания этих строк в LLDB, к сожалению, нет совсем.
Дополнение: Один простой, но эффективный отладочный прием