閱讀345 返回首頁    go 阿裏雲 go 技術社區[雲棲]


如何調試係統啟動過程中systemd的代碼

之前寫過很多kernel的gdb debug, 其實用戶態也是可以調試的, 隻是在共享庫的動態地址上不是很好處理, 最近同事有調試係統啟動過程中systemd的需求, 簡單研究了一下

其實qemu kvm打斷點並不區別kernel還是用戶態, 都是rip的值等於某個地址或者遇到斷點指令了, 所以開機的時候把斷點打到systemd的main上就可以了

但是其實另外一個問題是, 用戶態的地址是很多進程共享的, 這時候有可能會另一個進程也跑到了這個地址, 所以斷點就需要條件斷點, 用進程的pid是一個好方法,

下麵是簡單得步驟
第一步, 開機暫停

sudo qemu-system-x86_64 -drive file=centos7.vhd,if=virtio -vnc :11 -enable-kvm  -serial mon:stdio -smp 8 -m 1024 -redir tcp:1011::22 -append "root=/dev/vda1 console=ttyS0 slub_debug=PFZ ro norandmaps" -kernel /home/shidao.ytt/alikernel/7u/arch/x86/boot/bzImage -s -S

kernel 參數 norandmaps很重要, 不然的話, 共享庫的地址每次都不一樣, 加了這個參數, 每次共享庫的地址都是一樣的, 就不用考慮共享庫動態地址的問題了

第二步, 連接qemu, 打斷點到systemd的main

/usr/bin/gdb vmlinux -ex 'target remote :1234' -ex 'thb start_kernel' -ex c

(gdb) add-symbol-file /usr/lib/debug/usr/lib/systemd/systemd.debug 0x0000555555573b60

這裏說明一下, 因為要調試guest的systemd代碼, 所以要在物理機上安裝guest的systemd的debuginfo, 這個很好處理, 去centos下載debuginfo rpm安裝就可以了

後麵的地址0x0000555555573b60是systemd映射到進程代碼段的加載地址, 這個地址如何獲得, 開機一次, 去查看pid 1進程的vm映射空間就可以了, 簡單一點就是gdb -p 1, info files就可以了

(gdb) thbreak *0x5555555752c0 if $lx_current().pid == 1
Hardware assisted breakpoint 2 at 0x5555555752c0: file src/core/main.c, line 1244.

簡單說明, 因為systemd進程都還沒起來, 所以是沒有這個地址的, 所以一定需要用hardware breakpoint, 後麵是條件判斷, 隻有pid為1的時候生效, 這個就是斷點打到具體進程的利器了

c
接著跑
![image.png](https://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/f0b46477c660776e64219e06c60084f9.png)

隻要打斷點的時候加入pid的條件限製, 就可以打到任意的進程了

最後更新:2017-09-05 16:02:32

  上一篇:go  redis4.0之Lua腳本新姿勢
  下一篇:go  前端JS如何獲取主域名(根域名)