|
逍遙山水憶秋年 |
一般對 linux 使用 qemu + gdb 的除錯方式, 大概都是從 start_kernel 開始, 要是想要從 decompress 開始追起的話, 該怎麼辦呢?
我突然對這有了興趣, 看看怎麼處理。
不過要先來編譯 kernel:
make i386_defconfig
make
首先 decompress 這部份的程式碼在 linux-5.1.15/arch/x86/boot/compressed, 編譯好之後, linux-5.1.15/arch/x86/boot/compressed 也有個 vmlinux, 很可惜, 這個不能拿來當成 debug symbol, 所以幫 linux-5.1.15/arch/x86/boot/compressed/Makefile 加上 -g
KBUILD_CFLAGS := -m$(BITS) -O2
+KBUILD_CFLAGS := -m$(BITS) -O0 -g
一般我還會把 -O2 改成 -O0, 不知道為什麼, -O2 編譯之後, linux-5.1.15/arch/x86/boot/compressed/vmlinux 會有些 symbol 找不到, 例如: parse_elf, handle_relocations, nm linux-5.1.15/arch/x86/boot/compressed/vmlinux 是看不到他們的。
這樣重新編譯之後, linux-5.1.15/arch/x86/boot/compressed/vmlinux 才能拿來當 debug symbol 並拿來載入 gdb。
使用 qemu 執行 kernel
qemu-system-i386 -kernel arch/x86/boot/bzImage
啟用 gdb:
qemu-system-i386 -kernel arch/x86/boot/bzImage -S -s
我不知道神奇的 -kernel 是怎麼載入 kernel (似乎是 multiboot 或是特別認出 linux kernel), 不過在我的平台, 可以用 b *0x100000 將 kernel 停在 linux-5.1.15/arch/x86/boot/compressed/head_32.S L64, 你一定很疑惑我是怎麼找到這個位址的吧!
qemu 沒有 bochs 的 magic break point, 所以沒辦法很輕鬆的停在某行程式碼, 我用猜的, 然後在 L65 的地方加入無窮迴圈, 中斷 gdb, 使用 i r eip 查看目前的位址, 很幸運, 就這樣被我找到了。
我不確定這就是 linux kernel 的第一行程式碼進入點, 因為還看到一些其他的程式碼, 但應該是了。
head_32.S L144, L145, L213, L214 是跳到 .text relocated 處, 這裡是載入除錯 symbol 的關鍵。
2:
movl BP_code32_start(%esi), %eax
leal startup_32(%eax), %eax
jmp *%eax # 跳到 L214
ENDPROC(efi32_stub_entry)
#endif
.text
relocated:
想辦法得知 %eax 的內容, 其實就是 runtime 的 relocated 位址。
add-symbol-file vmlinux 0x1fa23c4
0x1fa23c4 是在我 qemu 上的值, 這裡就是 .text 的開始, symbol 載入到這位址, 就可以對
linux-5.1.15/arch/x86/boot/compressed/vmlinux 做 source code debug。
list 1 就是我把中斷點設定在
extract_kernel
parse_elf
handle_relocations
startup_32 會在 0x100000, 我從這裡把
movl $LOAD_PHYSICAL_ADDR, %ebx
1:
/* Target address to relocate to for decompression */
movl BP_init_size(%esi), %eax
subl $_end, %eax
addl %eax, %ebx
%ebx 的值印出來。
b *0x100000
b *0x100026
b *0x100078 # linux-5.1.15/arch/x86/boot/compressed/head_32.S L208
gdb -x g.sh
call extract_kernel 之後, L264 就會跳到解開的 kernel - linux-5.1.15/arch/x86/kernel/head_32.S, 從 startup_32 開始執行下去。
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。