1 利用virt-manager創(chuàng)建需要虛擬機(jī)
2 更換虛擬機(jī)的內(nèi)核到需要調(diào)試的內(nèi)核.
3 virsh edit <vm_name> 更改虛擬機(jī)配置,使其支持調(diào)試
<domain type='kvm' xmlns:qemu='[http://libvirt.org/schemas/domain/qemu/1.0'
<qemu:commandline>
<qemu:arg value='-s'/>
</qemu:commandline>
注意 只加-s 參數(shù)即可。
Qemu arg
4 拷貝虛擬機(jī)里的編譯好的內(nèi)核到宿主機(jī),并進(jìn)入 gdb 調(diào)試
scp -r linux-4.18.20 root@10.190.2.19:~
gdb vmlinux
target remote 127.0.0.1:1234
5 在 do_init_module 添加斷點(diǎn)并繼續(xù)執(zhí)行。
b do_init_module
c
6 在虛擬機(jī)上插入需要調(diào)試的模塊:
insmod progger_trace.ko
7 gdb 里打印 text section,data section 和 bss section 的名稱和地址:
print mod->sect_attrs->attrs[1]->name
print mod->sect_attrs->attrs[7]->name
print mod->sect_attrs->attrs[9]->name
print /x mod->sect_attrs->attrs[1]->address
print /x mod->sect_attrs->attrs[7]->address
print /x mod->sect_attrs->attrs[9]->address
8 根據(jù)上面打印的地址導(dǎo)入編譯好的內(nèi)核模塊
add-symbol-file /root/progger/linux_progger/progger_trace.ko <text addr> -s .data <data addr> -s .bss <bss addr>
9 下面就可以在模塊代碼中添加斷點(diǎn)并單步調(diào)試了:
編譯內(nèi)核
yum groupinstall "Development Tools"
make menuconfig
make -j 4
make modules
make modules_install
sudo make install
錯(cuò)誤:
Remote 'g' packet reply is too long 錯(cuò)誤的原因
這個(gè)錯(cuò)誤是當(dāng)目標(biāo)程序執(zhí)行時(shí)發(fā)生模式切換(real mode 16bit -> protected mode 32bit -> long mode 64bit)的時(shí)候,gdb server(此處就是 qemu)發(fā)送了不同長(zhǎng)度的信息,gdb 無(wú)法正確的處理這種情況,所以直接就報(bào)錯(cuò)。 此時(shí)需要斷開(kāi)連接并切換 gdb 的 arch (i386:x86-64 和 i386:x86-64:intel ),arch 變化后,gdb 會(huì)重新設(shè)置緩沖區(qū),然后再連接上去就能正常調(diào)試。這個(gè)方法規(guī)避了一些麻煩,但是實(shí)際上有兩種正規(guī)的解決方案:
(1) 修改 gdb 的源碼,使 gdb 支持這種長(zhǎng)度變化(gdb 開(kāi)發(fā)者似乎認(rèn)為這個(gè)問(wèn)題應(yīng)該由 gdb server 解決).
(2) 修改 qemu 的 gdb server,始終發(fā)送 64bit 的消息(但是這種方式可能導(dǎo)致無(wú)法調(diào)試 real mode 的代碼)
解決方法:
1 修改gdb代碼,打patch。
2 # 斷開(kāi) gdb 的連接
disconnect
# 重新設(shè)置 arch
# 此處設(shè)置和之前 show arch 的要不一樣
# 之前是 i386:x86-64 于是改成 i386:x86-64:intel
set arch i386:x86-64:intel
cannot access memory 解決方法主要看4
因?yàn)閮?nèi)核啟用這項(xiàng)特性之后,內(nèi)核啟動(dòng)時(shí)會(huì)隨機(jī)化內(nèi)核的各個(gè) section 的虛擬地址(VA),導(dǎo)致 gdb 斷點(diǎn)設(shè)置在錯(cuò)誤的虛擬地址上,內(nèi)核執(zhí)行時(shí)就不會(huì)觸發(fā)這些斷點(diǎn)。
可以更改/etc/grub2.conf 添加 nokasrl 命令參數(shù)。
然后`grub2-mkconfig -o /boot/grub2/grub.cfg`
或者取消 Processor type and features -> Build a relocatable kernel
取消后 Build a relocatable kernel 的子項(xiàng) Randomize the address of the kernel image (KASLR) 也會(huì)一并被取消
參考:
1 https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2016/06/21/gdb-linux-kernel-by-qemu
2 https://linux.cn/article-9665-1.html
3 https://imkira.com/a21.html
4 https://stackoverflow.com/questions/44612822/why-gdb-cannot-find-the-source-lines-of-the-linux-kernel-when-debugging-through