Вопрос по gdb, linux, linux-kernel, qemu – Как отладить ядро Linux с помощью GDB и QEMU?

28

Я новичок в разработке ядра, и я хотел бы знать, как запустить / отладить ядро 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, подключить к нему мой отладчик и, таким образом, заставить их работать вместе, чтобы облегчить мою жизнь с разработкой ядра.

Ваш Ответ

5   ответов
3

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

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
Разве не проблематично, что qemu и host используют одни и те же интерфейсы? Например, если это последовательный GPS, хост может уже использовать этот последовательный интерфейс.
@ransh Извините, я не понимаю ваш комментарий. При использовании qemu последовательное устройство не используется-s вариант, он использует вместо сокета TCP.
24

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

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

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

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

Разве не проблематично, что qemu и host используют одни и те же интерфейсы? Например, если это последовательный GPS, хост может уже использовать этот последовательный интерфейс.
Большое спасибо, это работает :). Я только что закончил читать книгу о DDD, eclipse и gdb, опубликованную не крахмальной прессой, но в этой книге не было удаленной отладки. Мое ядро сейчас запускается, но, похоже, для его загрузки требуется время (так как Qemu использует только 1 поток на моей машине), и теперь оно заблокировано по адресу:? kernel_thread_helper + 0x0 / 0x10. Это способ использования ядра для загрузки? Я имею в виду, разве у нас не должно быть командной строки после ее загрузки? Спасибо E-Kami
меня устраивает. Тем не менее, я не знаю, как принудительно остановить ядро на точке останова после вызова первого продолжения. Например, я поставил точку останова в функции start_kernel, но она никогда не остановится на этом. Любая идея ?
2

используя gdb, первое, что нужно сделать на gdb - это ввести cmds:

(gdb) целевой удаленный локальный хост: 1234

(gdb) break start_kernel

(Продолжить)

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

Разве не проблематично, что qemu и host используют одни и те же интерфейсы? Например, если это последовательный GPS, хост может уже использовать этот последовательный интерфейс.
Я использую eclipse для отладки ядра, запущенного в qemu, и установил stop на start_kernel. Но он по-прежнему запускается после отладки eclipse start. Я установил qemu остановлено, когда он запускается, и использую только GDB в порядке.
19

Step-by-step procedure tested on Ubuntu 16.10 host

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

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

a minimal init-only executable image: https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579 a Busybox interactive system: https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Тогда на ядре Linux:

git checkout v4.15
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 \
                   -append nokaslr

На другом терминале, внутри дерева ядра 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

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

https://sourceware.org/bugzilla/show_bug.cgi?id=13984 might be a GDB bug Remote 'g' packet reply is too long http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org is as usual an awesome source for these problems https://lists.nongnu.org/archive/html/qemu-discuss/2014-10/msg00069.html nokaslr: https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb/421287#421287

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

the Linux kernel does not support (and does not even compile without patches) with -O0: How to de-optimize the Linux kernel to and compile it with -O0? GDB 7.11 will blow your memory on some types of tab completion, even after the max-completions fix: Tab completion interrupt for large binaries Likely some corner case which was not covered in that patch. So an ulimit -Sv 500000 is a wise action before debugging. Blew up specifically when I tab completed file<tab> for the filename argument of sys_execve as in: https://stackoverflow.com/a/42290593/895245

Смотрите также:

https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging.rst official Linux kernel "documentation" Linux kernel live debugging, how it's done and what tools are used?
1

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

Похожие вопросы