Как отладить ядро ​​Linux с помощью GDB и QEMU?

Я новичок в разработке ядра, и я хотел бы знать, как запускать/отлаживать ядро ​​Linux с помощью QEMU и gdb. Я действительно читаю книгу Роберта Люка, но, к сожалению, это не помогает читателю о том, как установить правильные инструменты для запуска или отладки ядра... Так что я сделал это, следуя этому руководству http://opensourceforu.efytimes.com/2011/02/kernel-development-debugging-using-eclipse/. Я использую eclipse как IDE для разработки на ядре, но сначала хочу, чтобы он работал в QEMU/gdb. Так что я сделал до сих пор:

1) Чтобы скомпилировать ядро ​​с помощью:

make defconfig (then setting the CONFIG_DEBUG_INFO=y in the .config)
make -j4

2) После завершения компиляции я запускаю Qemu, используя:

qemu-system-x86_64 -s -S /dev/zero -kernel /arch/x86/boot/bzImage

которые запускают ядро ​​в состоянии "остановлено"

3) Таким образом, я должен использовать gdb, я пробую следующую команду:

gdb ./vmlinux

которые запускают его правильно, но... Теперь я не знаю, что делать... Я знаю, что мне нужно использовать удаленную отладку на порте 1234 (порт по умолчанию, используемый Qemu), используя vmlinux в качестве символа файл таблицы для отладки.

Итак, мой вопрос: что мне делать, чтобы запустить ядро ​​на Qemu, присоединить к нему отладчик и, таким образом, заставить их работать вместе, чтобы облегчить мою жизнь с развитием ядра.

Ответ 1

Я бы попробовал:

(gdb) target remote localhost:1234
(gdb) continue

Используя параметр "-s", qemu прослушивает порт tcp:: 1234, к которому вы можете подключиться как localhost: 1234, если вы находитесь на том же компьютере. Опция Qemu -S позволяет остановить выполнение Qemu до тех пор, пока вы не дадите команду continue.

Лучше всего, наверное, взглянуть на достойный учебник GDB, чтобы ладить с тем, что вы делаете. Этот выглядит довольно хорошо.

Ответ 2

Пошаговая процедура, протестированная на хосте Ubuntu 16.10

Чтобы начать работу с нуля, я сделал минимально полностью автоматизированный пример QEMU + Buildroot: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md Основные шаги ниже.

Сначала получите корневую файловую систему rootfs.cpio.gz. Если вам это нужно, подумайте:

Затем на ядре Linux:

git checkout v4.9
make mrproper
make x86_64_defconfig
cat <<EOF >.config-fragment
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
EOF
./scripts/kconfig/merge_config.sh .config .config-fragment
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
                   -initrd rootfs.cpio.gz -S -s

На другом терминале, изнутри дерева ядра Linux, предположим, что вы хотите начать отладку из start_kernel:

gdb \
    -ex "add-auto-load-safe-path $(pwd)" \
    -ex "file vmlinux" \
    -ex 'set arch i386:x86-64:intel' \
    -ex 'target remote localhost:1234' \
    -ex 'break start_kernel' \
    -ex 'continue' \
    -ex 'disconnect' \
    -ex 'set arch i386:x86-64' \
    -ex 'target remote localhost:1234'

и мы закончили!!

Для модулей ядра смотрите: Как отлаживать модули ядра Linux с помощью QEMU?

Для Ubuntu 14.04 необходим GDB 7.7.1, hbreak, break контрольные точки программного обеспечения были проигнорированы. Больше не в 16.10. См. Также: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

Беспокойный disconnect, и что после него нужно обойти ошибку:

Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000

Связанные темы:

Известные ограничения:

См. также:

Ответ 3

Ответ BjoernID на самом деле не работал у меня. После первого продолжения точка останова не достигнута и при прерывании я бы увидела такие строки, как:

0x0000000000000000 in ?? ()
(gdb) break rapl_pmu_init
Breakpoint 1 at 0xffffffff816631e7
(gdb) c
Continuing.
^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..]

Я предполагаю, что это имеет какое-то отношение к разным режимам процессора (реальный режим в BIOS по сравнению с длинным режимом при загрузке Linux). Во всяком случае, решение состоит в том, чтобы запустить QEMU сначала без ожидания (т.е. Без -S):

qemu-system-x86_64 -enable-kvm -kernel arch/x86/boot/bzImage -cpu SandyBridge -s

В моем случае мне нужно было что-то сломать во время загрузки, поэтому после некоторых децибел, я запустил команду gdb. Если у вас больше времени (например, вам нужно отлаживать модуль, который загружается вручную), то время не имеет большого значения.

gdb позволяет вам указывать команды, которые должны запускаться при запуске. Это упрощает автоматизацию. Чтобы подключиться к QEMU (который теперь должен быть запущен), перерыв функции и продолжение выполнения, используйте:

gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux

Ответ 4

Когда вы пытаетесь запустить vmlinux exe с помощью gdb, то первым делом на gdb является выпуск cmds:

(gdb) target remote localhost: 1234

(gdb) break start_kernel

(продолжение)

Это сломает ядро ​​в start_kernel.

Ответ 5

Для меня лучшим решением для отладки ядра является использование gdb из среды Eclipse. Вы должны просто установить соответствующий порт для gdb (должен совпадать с тем, который вы указали в строке запуска qemu) в разделе удаленной отладки. Вот руководство: http://www.sw-at.com/blog/2011/02/11/linux-kernel-development-and-debugging-using-eclipse-cdt/