как отладить ядро linux с помощью gdb и qemu?

<p>я новичок в разработке ядра, и я хотел бы знать, как запустить/отладить ядро linux, используя qemu и gdb. на самом деле я читаю книгу роберта лава, но, к сожалению, она не помогает читателю в том, как установить надлежащие инструменты для запуска или отладки ядра ... так что я сделал, следуя этому руководству <a href="http://opensourceforu.efytimes.com/2011/02/kernel-development-debugging-using-eclipse/">http: //opensourceforu.efytimes .com/2011/02/kernel-development-debugging-using-eclipse/</a> . я использую eclipse в качестве ide для разработки на ядре, но сначала я хотел, чтобы он работал под qemu/gdb. итак, что я сделал до сих пор:</p><p>1) скомпилировать ядро с:</p><pre><code>make defconfig (then setting the config\_debug\_info=y in the .config) make -j4 </code></pre><p>2) после завершения компиляции я запускаю qemu, используя:</p><pre><code>qemu-system-x86\_64 -s -s /dev/zero -kernel /arch/x86/boot/bzimage </code></pre><p>которые запускают ядро в "остановленном" состоянии</p><p>3) таким образом, я должен использовать gdb, я пытаюсь следующую команду:</p><pre><code>gdb ./vmlinux </code></pre><p>который запускает его правильно, но ... теперь я не знаю, что делать ... я знаю, что я должен использовать удаленную отладку на порту 1234 (порт по умолчанию, используемый qemu), используя vmlinux в качестве файла таблицы символов для отладки.</p><p>поэтому мой вопрос: что я должен сделать, чтобы запустить ядро в qemu, подключить к нему мой отладчик и, таким образом, заставить их работать вместе, чтобы облегчить мою жизнь с разработкой ядра.</p>

<p>я бы попробовал:</p><pre><code>(gdb) target remote localhost:1234 (gdb) continue </code></pre><p>использование опции '-s' заставляет qemu прослушивать порт tcp :: 1234, к которому вы можете подключиться как localhost: 1234, если вы находитесь на той же машине. опция '-s' в qemu заставляет qemu останавливать выполнение, пока вы не дадите команду продолжения.</p><p>лучше всего было бы взглянуть на приличный учебник gdb, чтобы понять, что вы делаете. <a href="https://web.archive.org/web/20180401080715/www.dirac.org/linux/gdb/">этот</a> выглядит довольно приятно.</p>

<p><strong>пошаговая процедура протестирована на хосте ubuntu 16.10</strong></p><p>чтобы быстро начать с нуля, я сделал минимальный полностью автоматизированный пример qemu + buildroot по адресу: <a href="https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md">https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-ugtep-. md</a> основные шаги описаны ниже.</p><p>сначала получите корневую файловую систему <code>rootfs.cpio.gz</code>. если вам это нужно, подумайте:</p><ul> <li>минимальный <code>init</code>- только исполняемый образ: <a href="https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579">https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579</a> </li> <li>интерактивная система busybox: <a href="https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902">https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902</a> </li> </ul><p>тогда на ядре linux:</p><pre><code>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' </code></pre><p>и мы сделали !!</p><p>для модулей ядра см .: <a href="https://stackoverflow.com/questions/28607538/how-to-debug-linux-kernel-modules-with-qemu/44095831#44095831">как отлаживать модули ядра linux с qemu?</a> </p><p>для ubuntu 14.04, gdb 7.7.1, была нужна <code>hbreak</code>, программные точки останова <code>break</code> игнорировались. не так больше в 16.10. смотрите также: <a href="https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944">https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944</a> </p><p>грязный <code>disconnect</code> и то, что следует за ним, должны обойти ошибку:</p><pre><code>remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000 </code></pre><p>связанные темы:</p><ul> <li> <a href="https://sourceware.org/bugzilla/show\_bug.cgi?id=13984">https://sourceware.org/bugzilla/show\_bug.cgi?id=13984</a> может быть ошибкой gdb</li> <li> <a href="https://stackoverflow.com/questions/8662468/remote-g-packet-reply-is-too-long">удаленный ответ пакета 'g' слишком длинный</a> </li> <li> <a href="http://wiki.osdev.org/qemu\_and\_gdb\_in\_long\_mode">http://wiki.osdev.org/qemu\_and\_gdb\_in\_long\_mode</a> osdev.org, как обычно, отличный источник этих проблем</li> <li> <a href="https://lists.nongnu.org/archive/html/qemu-discuss/2014-10/msg00069.html">https://lists.nongnu.org/archive/html/qemu-discuss/2014-10/msg00069.html</a> </li> <li><code>nokaslr</code>: <a href="https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb/421287#421287">https://unix.stackexchange.com/questions/397939/turning-off-kaslr-to-debug-linux-kernel-using-qemu-and-gdb/421287#421287</a> </li> </ul><p>известные ограничения:</p><ul> <li>ядро linux не поддерживает (и даже не компилирует без исправлений) с <code>-o0</code>: <a href="https://stackoverflow.com/questions/29151235/how-to-de-optimize-the-linux-kernel">как де-оптимизировать ядро linux и скомпилировать его с -o0?</a> </li> <li>gdb 7.11 разрушит вашу память при некоторых типах завершения табуляции, даже после исправления <code>max-completions</code>: <a href="https://stackoverflow.com/questions/597777/tab-completion-interrupt-for-large-binaries">прерывание завершения табуляции для больших двоичных файлов</a> вероятно, какой-то угловой случай, который не был описан в этом патче. так что <code>ulimit -sv 500000</code> - мудрое действие перед отладкой. в частности, взорвался, когда я завершил вкладку <code>file<tab></code> для аргумента <code>filename</code> <code>sys\_execve</code>, как в: <a href="https://stackoverflow.com/a/42290593/895245">https://stackoverflow.com/a/42290593/895245</a> </li> </ul><p>смотрите также:</p><ul> <li> <a href="https://github.com/torvalds/linux/blob/v4.9/documentation/dev-tools/gdb-kernel-debugging.rst">https://github.com/torvalds/linux/blob/v4.9/documentation/dev-tools/gdb-kernel-debugging.rst</a> "официальная" документация по ядру linux</li> <li> <a href="https://stackoverflow.com/questions/4943857/linux-kernel-live-debugging-how-its-done-and-what-tools-are-used">отладка ядра linux в реальном времени, как это делается и какие инструменты используются?</a> </li> </ul>

<p>ответ бьорнида не сработал для меня. после первого продолжения точка останова не достигается, и при прерывании я бы увидел такие строки:</p><pre><code>0x0000000000000000 in ?? () (gdb) break rapl\_pmu\_init breakpoint 1 at 0xffffffff816631e7 (gdb) c continuing. ^cremote 'g' packet reply is too long: 08793000000000002988d582000000002019[..] </code></pre><p>я предполагаю, что это как-то связано с разными режимами процессора (реальный режим в bios или длинный режим, когда linux загрузился). в любом случае, решение состоит в том, чтобы сначала запустить qemu без ожидания (то есть без <code>-s</code>):</p><pre><code>qemu-system-x86\_64 -enable-kvm -kernel arch/x86/boot/bzimage -cpu sandybridge -s </code></pre><p>в моем случае мне нужно было что-то сломать во время загрузки, поэтому через несколько секунд я запустил команду gdb. если у вас есть больше времени (например, вам нужно отладить модуль, загруженный вручную), тогда время не имеет значения.</p><p><code>gdb</code> позволяет указать команды, которые должны запускаться при запуске. это делает автоматизацию немного проще. чтобы подключиться к qemu (который уже должен быть запущен), прервать функцию и продолжить выполнение, используйте:</p><pre><code>gdb -ex 'target remote localhost:1234' -ex 'break rapl\_pmu\_init' -ex c ./vmlinux </code></pre>

<p>когда вы пытаетесь запустить vmlinux exe, используя gdb, первое, что нужно сделать на gdb - это ввести cmds:</p><p>(gdb) целевой удаленный локальный хост: 1234</p><p>(gdb) break start\_kernel</p><p>(продолжить)</p><p>это сломает ядро в start\_kernel.</p>

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