четверг, 25 июля 2013 г.

PhantomEx: VMware + gdb + eclipse

"Если ваш единственный инструмент — молоток, то каждая проблема становится похожей на гвоздь".

Абрахам Маслоу


Так вот в нашем ремесле настала пора заменить молотки на что-то более хирургически точное.

До сих пор мы использовали в качестве "среды" разработки обычный текстовый редактор, для сборки проекта - утилиту make, а отлаживали исключительно путем запуска нашего ядра на виртуальной машине QEMU.

Но наступает момент когда объем кода и сложность алгоритма становятся такими, что этим минимальным набором уже не обойтись. Давайте настроим для нашего проекта среду разработки и отладки.



1. Настройка IDE. Мигрируем проект в Eclipse


Сред разработки для С/С++ под линуксом великое множество, однако после нескольких экспериментов мой выбор пал на Eclipse CDT. Эта среда доступна для скачивания на официальном сайте, но для пользователей Linux она обязательно найдется в репозитории вашего дистрибьютора, как например у меня в Arch Linux

$ sudo pacman -S eclipse eclipse-cdt

и всё ок, ваша IDE уже установлена. Запускаем её командой

$ eclipse

и увидим мы что-то похожее. Но совсем похожим оно станет когда мы настроим наш проект для разработки в Eclipse. Лезем в меню File > New > Project и нам предложат выбрать тип проекта


выбираем Makefile Project with Existing Code - проект на основе make-файла с существующим исходным кодом, именно это и есть у нас в данный момент.

Жмем "Next" на следующем окне нам предлагают ввести имя проекта и указать где взять его исходники, а так же выбрать инструментальные средства для его сборки. Я сделал так, как показано на нижеприведенном скриншоте


Жмем "Finish" - всё, проект готов к работе


Теперь нам доступны все вкусности, которые дает развитая среда разработки - просмотр файлов проекта, продвинутые функции редактирования и прочие маленькие радости жизни. Для сборки или очистки проекта лезем в меню Project и находим там пункты Build All и Clean. Всё будет работать сразу, так как среда произведет сборку по имеющемуся у нас Makefile.

2. Настройка интерфейса к отладчику GDB.


Что ни говори, а GNU Debugger - стандарт де-факто при разработке на линукс-платформе, и пока что вряд ли что-то способно с ним конкурировать. Но наша задача не тривиальна - мы разрабатываем ядро ОС, можно ли использовать GDB для такого проекта? Нужно!

Эмулятор QEMU, который мы использовали, поддерживает отладку с помощью GDB, для этого к команде запуска надо добавить ключи -s -S. У себя я проделывал сие многократно, ВМ останавливалась, ожидая подключения отладчика, реагировала на точки останова но... пошаговую отладку напрочь отказывалась производить. Не знаю почему.

Та же ситуация повторилась и с Bochs, хотя давным давно я использовал его для этой цели, не помогли и статьи Криса Касперски о сборке этого эмулятора для поддержки отладки в 64-битной хост-системе... Может делов 64-разрядности моей линукс-платформы, может ещё в чем, но почти потеряв надежду я обратился к VMware Workstation 9.

Этот проприетарный эмулятор, один из старейших и мощнейщих на сегодняшний день (позволяющий даже играть под ним в WoT) не сплоховал и тут.

Прежде всего конвертируем наш виртуальный HDD в формат *.vmdk, который использует VMware

$ qemu-img convert -f raw -O vmdk ~/MyOSkernel/hard_disk.img ~/MyOSkernel/hdd/hard_disk.vmdk

используем утилиту qemu-img для работы с образами HDD. При объеме нашего винта в 2 Гб конвертация займет мгновение.

Создаем виртуальную машину, в качестве типа ОС выбирает демократичны "Other" в качестве файла HDD - наш существующий образ *.vmdk, на предложение конвертировать его в новый формат VMware я ответил отказом, на всякий случай. Всё готово )


Теперь идем в каталог с виртуальной машиной, находим там файл типа *.vmx (в нашем примере, допустим MySuperOS.vmx). Он текстовый, в его конец добавляем такие строки

debugStub.listen.guest32 = "TRUE"
debugStub.listen.guest32.remote = "TRUE"
debugStub.hideBreakpoints = "TRUE"
monitor.debugOnStartGuest32 = "TRUE"

что открывает доступ к функции gdb-stub - интерфейс с отладчиком gdb. Кроме этого в настройках самой ВМ включаем полную отладочную информацию
Ещё необходимо включить сетевые службы, для чего в консоли выполняем

$ sudo vmware-networks --start

для запуска сетевого интерфейса с хост-системой.

Теперь запускаем виртуальную машину и видим картину
Это означает, что виртуалка ждет пока мы подключимся к ней из GDB. Запускам отладчик в консоли

$ gdb -q -tui

Ключ указан -q для того чтобы дебаггер не надоедал сообщениями о своей принадлежности к проекту GNU и не загаживал консоль ненужным текстом, а ключ -tui - для доступа к просмотру исходников в окне отладки. И попадаем мы в консоль gdb где вводим команду

(gdb) target remote localhost:8832

Эта команда конектит отладчик с виртуальной машиной, через локальный сетевой интерфейс через порт 8832, используемый vmware для удаленной отладки.

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

(gdb) symbol ~/MyOSkernel/src/kernel

Да-да, грузим в отладчик собранное ядро, мы ведь собирали его с ключом -g, если помните, и символьная информация имеется в бинарном файле.

Теперь мы можем поставить точку останова

(gdb) tb main

Отладчик буднично сообщит что установил временную точку останова на функцию main в файле main.c на строку номер 13. Так, теперь вводим команду

(gdb) c

и процесс пошел! И что же мы видим? Отладчик остановился на брейкпоинте, вывалив консоль исходник main.c и приглашает нас отлаживать.


Этого уже вполне сносно хватит для работы. Данная статья - не руководство по GDB, на то есть официальные документы проекта GNU, а для первоначального знакомства с GDB хорошо прочесть эту статью. Наша цель несколько иная, а именно

3. Интергация отладчика с IDE Eclipse


Да, давайте сделаем красиво, будем отлаживать наш проект непосредственно из IDE.

Для этого в Eclipse в меню Run выбираем пункт Debug Configarations, и создаем новую конфигурацию C/C++ Remote Application, как показано на скрине
Тут необходимо кое-то настроить, прежде всего соединение с VMware. Идем на вкладку Debugger, там выбираем вкладку Connection и вбиваем параметры коннекта с отладчиком

Жмем "Apply" и лезем на вкладку Main, с тем чтобы указать путь к бинарнику ядра для загрузки символьной информации в строке C/C++ Application.


Отлично, опять применяем настройки, запускаем виртуальную машину и жмем Debug. И видим мы вот такое чудо
Отладчик подключился к ВМ и передал нам управление в IDE. Теперь можно хоть до посинения ползать по исходникам, ставить точки останова, просматривать переменные, стек вызовов, в общем делать всё то что зовется пошаговой отладкой  в IDE.

Заключение


Теперь наши возможности выросли в сотни раз - мы собрали полноценную IDE на основе Eclipse, VMware и GDB и нас ничто не может остановить )