В поиске вопросов, или как создать новый отладчик
Мы уделяем много внимания инструментам разработки: участвуем в горячих спорах о редакторах (Vim или Emacs?), долго настраиваем IDE под свой вкус, и тщательно выбираем языки программирования и библиотеки, которые с каждым днем становятся все лучше и удобнее. Однако, здесь можно выделить одну категорию, которая по какой-то причине остается незаслуженно забытой: отладчики не сильно изменились за последний десяток лет, хотя по-прежнему являются одним из базовых инструментов для отлова ошибок и навигации в коде.
Изображение: Timothy Dykes @timothycdykes, unsplash.com
Гораздо чаще мы предпочитаем быстро добавить пару print
ов вместо того, чтобы поставить в нужном месте точку останова и пройтись к ней отладчиком — и вопрос «почему?» не перестает меня занимать — ведь логи и print
ы дают ограниченную информацию и не позволяют интерактивно взаимодействовать с запущенным процессом (а отладчики могут работать даже и с «умершими» процессами!).
Одной из главных причин я вижу как раз отсутствие значительного прогресса в разработке отладчиков.
GDB появился еще во времена Горбачева, и с тех пор не претерпел фундаментальных изменений. И хотя у нас уже есть скоростной интернет, большие экраны с разрешением в 4K, доступные восьми- и шестидесятиядерные процессоры, принцип работы с отладчиком не изменился существенным образом. В лучшем случае, мы получаем интеграцию с IDE и редакторами вроде VS Code (или с браузером, если это JavaScript), но отладчики по-прежнему не умеют по-настоящему понимать наш код и часто не могут дать ответов на сложные вопросы.
Эта ситуация довольно резко контрастирует с прогрессом в дизайне компиляторов и языков программирования. Такие языки как Rust, предлагающие стандартный набор незаменимых в современном мире инструментов разработки — хороший пример инновации в устоявшейся сфере системного программирования, где значительная часть инструментов застала уже даже не только Горбачева, но и Брежнева (например, программа Make была создана в 1976 году).
Но этого мало: сейчас архитектура компилятора Rust претерпевает большие изменения в направлении «библиотекизации» — то есть, в разделении на отдельные компоненты и сервисы, которые могут работать в отрыве от привычного монолитного компилятора. Этот процесс важен потому что сейчас компиляторы очень тесно интегрируются в общую среду разработки через «языковые серверы», и осуществляют такие функции, как дополнение кода или всплывающие подсказки. Более того, так как компилятор становится доступен в форме библиотеки, это создает новую инфраструктуру полезных пользовательских дополнений и инструментов — например, для статического анализа кода.
Но вернемся к проблеме отладчиков. Если мы заглянем под капот GDB и LLDB, то увидим довольно странную картину: поддержка для новых языков программирования (Go или Rust) реализуется не при помощи уже существующих компиляторов, а через написание отдельных парсеров выражений на C или C++. Возникает сложная проблема поддержки и порочный круг — отладчики не реализуют в полной мере все выразительные возможности языка, поэтому их мало кто использует — и потому что их мало кто использует, мало кто занимается их поддержкой и разработкой. В результате такой стагнации поддержка отдельных языков удаляется из основной кодовой базы — как это случилось с Go и Java в LLDB.
Что можно сделать, чтобы выпутаться из такой ситуации? Конечно, переписать все на Rust! Как показывает практика, создание новых современных отладчиков не настолько невероятная задача. Успех проекта Delve показывает, что отладчики заточенные под идиоматику отдельного языка (в данном случае — Go) востребованы, даже если поддерживается только архитектура x86–64 и ОС Windows/Linux/macOS.
Создавая новый инструмент отладки, мы должны делать его модульным, расширяемым, и с возможностью интеграции с компилятором. Это откроет широкие возможности: пользователи смогут создавать собственные доменно-ориентированные отладчики, которые будут иметь полный доступ к контексту конкретного приложения (по аналогии с доменно-ориентированными языками). Модульная структура позволит реализовать REPL или аналог Jupyter с визуализацией данных и возможностью писать хоть целые новые функции в рантайме (как в Пайтоне, Руби, и других языках с виртуальной машиной).
Сейчас в большинстве случаев такие возможности отсутствуют, и именно эти проблемы, а также куча времени, потерянного в попытках отлова ошибок, привели к идее нового проекта, призванного помогать находить ответы на сложные вопросы про выполнение кода.
Таким образом, я хочу анонсировать Headcrab, новую библиотеку для создания отладчиков. Пока что возможностей немного: можно создавать новые процессы, читать и записывать память, смотреть регистры процессора. Но это лишь начало, и цель на этот год — создать полноценный фреймворк для мини-отладчиков программ написанных на Расте.
Если вам интересно поучаствовать к разработке, мы будем рады вас поддержать, даже если системное программирование пока что для вас ново. Вы также поможете, если поделитесь своим опытом отладки: с какими проблемами вы сталкивались, какие инструменты используете, и что бы хотели видеть в новом отладчике?
Спасибо, что прочитали этот текст. :)