Remote GDB Debugging
binutils-aarch64-linux-gnu 套件缺乏 aarch64-linux-gnu-gdb,於是直接抓 binutils-gdb 下來編譯。
Build gdb
ubuntu 21.10
1 | git clone git://sourceware.org/git/binutils-gdb.git --depth=1 --branch gdb-11.2-release |
ubuntu 24.04
1 | git clone git://sourceware.org/git/binutils-gdb.git --depth=1 --branch gdb-13.1-release |
如果在 gdb 執行時看到這麼一段警告
1 | warning: Can not parse XML target description; XML support was disabled at compile time |
且無法看 aarch64 system registers
1 | (gdb) info all-registers |
那可先安裝 libexpat1-dev、在 configure 加入 --with-expat 來支援 Target Description
1 | apt install libexpat1-dev |
gdb client 會收到一份 Target Description - XML,能顯示 register 當前內容。
1 | (gdb) info registers |
Trouble shooting
編譯過程中可能發生錯誤
1 | error: expat is missing or unusable |
1 | checking whether to use expat... yes |
大概看了一下腳本是透過創立 XML_Parser 來檢查 expat 的存在
1 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libexpat" >&5 |
將這段程式碼拉出來單獨透過 aarch64-linux-gnu-gcc 編譯,看會遇到什麼問題
1 |
|
1 | aarch64-linux-gnu-gcc ./test.c $(pkg-config --libs expat) -o test |
加上 verbose 進行除錯
1 | /usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/bin/ld -lexpat --verbose |
Reference
透過 GDB 進行遠端除錯
為了方便將 gdb 設 alias
1 | alias aarch64-linux-gnu-gdb='~/Desktop/OSDI/binutils-gdb/gdb/gdb' |
運行 qemu 實體
-s: 在 port 1234 開啟gdbserver-S: 在 monitor 按下 c 才開始運行
1 | qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial pty -monitor stdio -S -s |
在另一個視窗開啟 gdb
1 | ~$ aarch64-linux-gnu-gdb |
設定中斷點
1 | (gdb) b _start |
又或者在 qemu monitor 暫停模擬
1 | (qemu) stop |
同時 gdb 視窗可見以下輸出
1 | Thread 1 received signal SIGINT, Interrupt. |
Reference:
- [透過 GDB 進行遠端除錯](https://hackmd.io/@sysprog/gdb-example
AArch64 calling convention
The 64-bit ARM (AArch64) calling convention allocates the 31 general-purpose registers as:[2]
x31 (SP): Stack pointer or a zero register, depending on context.
x30 (LR): Procedure link register, used to return from subroutines.
x29 (FP): Frame pointer.
x19 to x29: Callee-saved.
x18 (PR): Platform register. Used for some operating-system-specific special purpose, or an additional caller-saved register.
x16 (IP0) and x17 (IP1): Intra-Procedure-call scratch registers.
x9 to x15: Local variables, caller saved.
x8 (XR): Indirect return value address.
x0 to x7: Argument values passed to and results returned from a subroutine.
All registers starting with x have a corresponding 32-bit register prefixed with w. Thus, a 32-bit x0 is called w0.
Similarly, the 32 floating-point registers are allocated as:[3]
v0 to v7: Argument values passed to and results returned from a subroutine.
v8 to v15: callee-saved, but only the bottom 64 bits need to be preserved.
v16 to v31: Local variables, caller saved.