以 bmcweb 为例,演示通过 qemu 进行 OpenBMC 应用的远程调试。
基础信息
bmcweb 基于 OpenBMC 最新的代码(v2.14+)进行构建;
基础运行环境基于 OpenBMC v2.8 进行构建,并启用了 NFS 支持(否则根本不可能有空间存储带调试符号的可执行文件和动态库);
flash 大小为 128M(默认的 32M 空间有点小,改成 128M 更方便,当然需要内核 dtb 以及 qemu 命令行等一系列的修改);
qemu 命令行如下:
❯ qemu-system-arm -m 1g -M romulus-bmc,fmc-model=mx66l1g45g -nographic -drive file=obmc-phosphor-image-romulus-20231227020028.static.mtd,format=raw,if=mtd -net nic -net user,hostfwd=::2222-:22,hostfwd=::2443-:443,hostfwd=udp::2623-:623,hostfwd=::1234-:1234,hostname=qemu
image w/ gdbserver
为 bmc 镜像增加 gdbserver 等调试工具:
❯ vi build/romulus/conf/local.conf
EXTRA_IMAGE_FEATURES ?= "debug-tweaks tools-debug"
app w/ debug info
需要准备的内容包括 bmcweb 自身以及它所依赖的 gcc-runtime, glibc, libgcc, boost 等动态库:
❯ tree
.
├── bmcweb
├── boost
│ ├── libboost_chrono.so.1.83.0
│ ├── libboost_context.so.1.83.0
│ ├── libboost_coroutine.so.1.83.0
│ ├── libboost_thread.so.1.83.0
│ └── libboost_url.so.1.83.0
├── gcc-runtime
│ ├── libatomic.so.1.2.0
│ ├── libgomp.so.1.0.0
│ ├── libitm.so.1.0.0
│ ├── libstdc++.so.6 -> libstdc++.so.6.0.32
│ └── libstdc++.so.6.0.32
├── glibc
│ ├── ld-linux.so.3
│ ├── libanl.so.1
│ ├── libBrokenLocale.so.1
│ ├── libc_malloc_debug.so.0
│ ├── libc.so.6
│ ├── libdl.so.2
│ ├── libmemusage.so
│ ├── libm.so.6
│ ├── libnsl.so.1
│ ├── libnss_compat.so.2
│ ├── libnss_db.so.2
│ ├── libnss_dns.so.2
│ ├── libnss_files.so.2
│ ├── libnss_hesiod.so.2
│ ├── libpcprofile.so
│ ├── libpthread.so.0
│ ├── libresolv.so.2
│ ├── librt.so.1
│ ├── libthread_db.so.1
│ └── libutil.so.1
└── libgcc
└── libgcc_s.so.1
注意拷贝 image 目录下的可执行文件和动态库,以 bcmweb 为例说明如下:
- image/usr/bin/bmcweb 是原始构建出来的带调试符号的 bmcweb 可执行文件;
- package/usr/bin/bmcweb 是 strip 了调试符号的 bmcweb 可执行文件;
- package/usr/bin/.debug/bmcweb 是 bmcweb 可执行文件的调试符号;
- packages-split/bmcweb/usr/bin/bmcweb 待打包的 strip 了调试符号的 bmcweb 可执行文件;
- packages-split/bmcweb-dbg/usr/bin/.debug/bmcweb 待打包的 bmcweb 可执行文件的调试符号;
是不是和 rpm 的构建似曾相识,以前的 OpenBMC 默认就是用的 rpm 格式打包,新版本才切成 ipk 格式。
修改 bmcweb 动态链接库的搜索路径:
❯ patchelf --set-interpreter ./glibc/ld-linux.so.3 --set-rpath '$ORIGIN:$ORIGIN/glibc:$ORIGIN/gcc-runtime:$ORIGIN/boost:$ORIGIN/libgcc' --force-rpath ./bmcweb
所有可执行文件和动态库拷贝到 NFS 共享上,OpenBMC 虚机通过 NFS 访问这些文件。
gdb remote debug
gdb server
挂载 NFS 共享:
root@romulus:~# mount -t nfs -o nfsvers=2 10.0.1.105:/home/runsisi/bmc /media/
通过 gdbserver 启动 bmcweb:
root@romulus:/media/bmcapp# gdbserver :1234 ./bmcweb
Process ./bmcweb created; pid = 748
Listening on port 1234
clion client
其中 Sysroot 通过如下脚本生成:
https://github.com/runsisi/obmc-utils/blob/master/obmc-sysroot.py
❯ python obmc-sysroot.py -b ~/working/bmc/openbmc/build/romulus -r ~/working/test/bmcroot
*** setup bmc sysroot succeeded! ***
export PATH=\
/home/runsisi/working/test/bmcroot/sysroot-native/usr/bin/arm-openbmc-linux-gnueabi:\
/home/runsisi/working/test/bmcroot/sysroot/usr/bin/crossscripts:\
/home/runsisi/working/test/bmcroot/sysroot-native/usr/sbin:\
/home/runsisi/working/test/bmcroot/sysroot-native/usr/bin:\
/home/runsisi/working/test/bmcroot/sysroot-native/sbin:\
/home/runsisi/working/test/bmcroot/sysroot-native/bin\
$PATH
GCC --sysroot=/home/runsisi/working/test/bmcroot/sysroot, e.g.,
arm-openbmc-linux-gnueabi-gcc --sysroot=/home/runsisi/working/test/bmcroot/sysroot -o x x.c
arm-openbmc-linux-gnueabi-gdb ./x
gdb client
设置通过 obmc-sysroot.py 生成的 PATH
环境变量,然后启动 arm-openbmc-linux-gnueabi-gdb 即可(相比 clion 主要是需要手工设置 substitute-path
会稍微麻烦一点点,同时 OpenBMC 默认构建的 gdb 没有 tui 之类的辅助,因此会更麻烦):
❯ arm-openbmc-linux-gnueabi-gdb
GNU gdb (GDB) 13.2
(gdb) file bmcweb
Reading symbols from bmcweb...
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
Reading symbols from ./glibc/ld-linux.so.3...
0x76feea90 in _start () from ./glibc/ld-linux.so.3
(gdb) b main
Breakpoint 1 at 0x43e1d4: file /usr/src/debug/bmcweb/1.0+git/src/webserver_main.cpp, line 157.
(gdb) set substitute-path /usr/src/debug/bmcweb/1.0+git /home/runsisi/working/bmc/openbmc/build/romulus/workspace/sources/bmcweb
(gdb) set substitute-path /usr/include/c++/13.2.0 /home/runsisi/working/test/bmcroot/sysroot/usr/include/c++/13.2.0
(gdb) c
当然,也可以直接安装 gdb-multiarch,这样会比直接使用 OpenBMC 默认构建的 gdb 更简单:
❯ sudo pacman -S gdb-multiarch
❯ gdb-multiarch
GNU gdb (GDB) 13.2
(gdb) file bmcweb
Reading symbols from bmcweb...
(gdb) set substitute-path /usr/src/debug/bmcweb/1.0+git /home/runsisi/working/bmc/openbmc/build/romulus/workspace/sources/bmcweb
(gdb) set sysroot /home/runsisi/working/test/bmcroot/sysroot
(gdb) b main
Breakpoint 1 at 0x3e1d4: file /usr/src/debug/bmcweb/1.0+git/src/webserver_main.cpp, line 157.
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
Reading symbols from ./glibc/ld-linux.so.3...
0x76feea90 in _start () from ./glibc/ld-linux.so.3
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0043e1d4 in main(int, char**)
at /usr/src/debug/bmcweb/1.0+git/src/webserver_main.cpp:157
appendix
Debugging Tools and Techniques
https://docs.yoctoproject.org/dev-manual/debugging.html
最后修改于 2024-01-03