GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara men-debug kernel Linux dengan GDB dan QEMU?

Saya akan mencoba:

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

Menggunakan opsi '-s' membuat qemu mendengarkan di port tcp::1234, yang dapat Anda sambungkan sebagai localhost:1234 jika Anda menggunakan mesin yang sama. Opsi '-S' Qemu membuat Qemu menghentikan eksekusi sampai Anda memberikan perintah continue.

Hal terbaik mungkin adalah melihat tutorial GDB yang layak untuk memahami apa yang Anda lakukan. Yang ini terlihat cukup bagus.


Prosedur langkah demi langkah diuji pada host Ubuntu 16.10

Untuk memulai dari awal dengan cepat, saya telah membuat contoh QEMU + Buildroot otomatis minimal di:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md Major langkah-langkah dibahas di bawah ini.

Pertama dapatkan filesystem root rootfs.cpio.gz . Jika Anda membutuhkannya, pertimbangkan:

  • minimal init -hanya gambar yang dapat dieksekusi:https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579
  • sistem interaktif Busybox:https://unix.stackexchange.com/questions/2692/what-is-the-smallest-possible-linux-implementation/203902#203902

Kemudian pada kernel 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

Di terminal lain, dari dalam pohon kernel Linux, misalkan Anda ingin memulai debug dari 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'

dan kita selesai!!

Untuk modul kernel, lihat:Bagaimana cara men-debug modul kernel Linux dengan QEMU?

Untuk Ubuntu 14.04, GDB 7.7.1, hbreak diperlukan, break breakpoint perangkat lunak diabaikan. Tidak demikian lagi di 16.10. Lihat juga:https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

disconnect yang berantakan dan apa yang terjadi setelahnya untuk mengatasi kesalahan:

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

Utas terkait:

  • https://sourceware.org/bugzilla/show_bug.cgi?id=13984 mungkin bug GDB
  • Balasan paket 'g' jarak jauh terlalu panjang
  • http://wiki.osdev.org/QEMU_and_GDB_in_long_mode osdev.org seperti biasa merupakan sumber yang luar biasa untuk masalah ini
  • 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

Batasan yang diketahui:

  • kernel Linux tidak mendukung (dan bahkan tidak dapat dikompilasi tanpa tambalan) dengan -O0 :Bagaimana cara menonaktifkan kernel Linux dan mengompilasinya dengan -O0?
  • GDB 7.11 akan menghabiskan memori Anda pada beberapa jenis penyelesaian tab, bahkan setelah max-completions perbaikan:Interupsi penyelesaian tab untuk binari besar Kemungkinan beberapa kasus sudut yang tidak tercakup dalam tambalan itu. Jadi sebuah ulimit -Sv 500000 adalah tindakan bijak sebelum debugging. Meledakkan secara khusus ketika tab saya menyelesaikan file<tab> untuk filename argumen sys_execve seperti di:https://stackoverflow.com/a/42290593/895245

Lihat juga:

  • https://github.com/torvalds/linux/blob/v4.9/Documentation/dev-tools/gdb-kernel-debugging. "dokumentasi" kernel Linux resmi pertama
  • Linux kernel live debugging, bagaimana melakukannya dan alat apa yang digunakan?

Jawaban BjoernID tidak terlalu berhasil untuk saya. Setelah kelanjutan pertama, tidak ada breakpoint yang tercapai dan saat interupsi, saya akan melihat baris seperti:

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

Saya kira ini ada hubungannya dengan mode CPU yang berbeda (mode nyata di BIOS vs. mode panjang ketika Linux telah di-boot). Bagaimanapun, solusinya adalah menjalankan QEMU terlebih dahulu tanpa menunggu (yaitu tanpa -S ):

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

Dalam kasus saya, saya perlu memecahkan sesuatu saat boot, jadi setelah beberapa detik, saya menjalankan perintah gdb. Jika Anda memiliki lebih banyak waktu (mis. Anda perlu men-debug modul yang dimuat secara manual), waktu tidak terlalu penting.

gdb memungkinkan Anda menentukan perintah yang harus dijalankan saat dimulai. Ini membuat otomatisasi sedikit lebih mudah. Untuk terhubung ke QEMU (yang seharusnya sudah dimulai), hentikan fungsi dan lanjutkan eksekusi, gunakan:

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

Linux
  1. Cara men-debug program C di Linux menggunakan gdb

  2. Flatpak di Linux:Apa Itu dan Bagaimana Menginstal Aplikasi dengannya

  3. Cara memeriksa Versi OS dan Linux

  1. Analisis kernel Linux dengan ftrace

  2. Cara Membuat Alias ​​​​dan Menggunakan Perintah Alias ​​​​di Linux

  3. Linux – Bagaimana Kernel Linux Mengetahui Nomor Mayor dan Minor Perangkat?

  1. Tonton perintah dan tugas dengan perintah jam tangan Linux

  2. Cara menangkap sesi terminal dan output dengan perintah skrip Linux

  3. Bagaimana cara membaca, memahami, menganalisis, dan men-debug kepanikan kernel Linux?