嵌入式设备上Bazel编译程序的本地GDB调试断点失效问题
编译配置与过程
使用Bazel结合TDA4 SOC交叉编译工具链编译hello-world程序,BUILD文件内容:
$ cat examples/hello_world/BUILD cc_binary( name = "hello_world", srcs = ["hello_world.cpp"], )
编译命令及输出:
$ bazel build --cxxopt=-std=c++11 --config=tda4 --copt=-DWITH_TDA4 --subcommands --copt=-DFOOFXXX -c dbg --strip=never //examples/hello_world:hello_world Starting local Bazel server and connecting to it... INFO: Analyzed target //examples/hello_world:hello_world (41 packages loaded, 40489 targets configured). INFO: Found 1 target... SUBCOMMAND: # //examples/hello_world:hello_world [action 'Compiling examples/hello_world/main.cpp', configuration: e23aa3bce872abfb8f06c09952a42b5c1c7714b1c55b5bf022d91a6582852828, execution platform: @local_config_platform//:host] (cd /home/wss/.cache/bazel/_bazel_wss/4112892ab2eb09dee5980f588ac10e42/execroot/com_minieye_aiplorer && \ exec env - \ LD_LIBRARY_PATH=/opt/ros/melodic/lib \ PATH=/opt/ros/melodic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin \ PWD=/proc/self/cwd \ bazel/toolchain/aarch64-none-linux-gnu/wrappers/aarch64-none-linux-gnu-gcc -MD -MF bazel-out/aarch64-dbg/bin/examples/hello_world/_objs/hello_world/main.d '-frandom-seed=bazel-out/aarch64-dbg/bin/examples/hello_world/_objs/hello_world/main.o' '-DBAZEL_CURRENT_REPOSITORY=""' -iquote . -iquote bazel-out/aarch64-dbg/bin -iquote external/bazel_tools -iquote bazel-out/aarch64-dbg/bin/external/bazel_tools '--sysroot=external/aarch64-none-linux-gnu-sysroot' -no-canonical-prefixes -fno-canonical-system-headers -Wno-builtin-macro-redefined '-D__DATE__="redacted"' '-D__TIMESTAMP__="redacted"' '-D__TIME__="redacted"' -DWITH_TDA4 -DFOOFXXX '-std=c++11' -c examples/hello_world/main.cpp -o bazel-out/aarch64-dbg/bin/examples/hello_world/_objs/hello_world/main.o) # Configuration: e53aa3bce872abfb8f06c29952a42b5c1c7714b1c55b5bf022d91a6582852828 # Execution platform: @local_config_platform//:host SUBCOMMAND: # //examples/hello_world:hello_world [action 'Linking examples/hello_world/hello_world', configuration: e23aa3bce872abfb8f06c09952a42b5c1c7714b1c55b5bf022d91a6582852828, execution platform: @local_config_platform//:host] (cd /home/wss/.cache/bazel/_bazel_wss/4112892ab2eb09dee5980f588ac10e42/execroot/com_minieye_aiplorer && \ exec env - \ LD_LIBRARY_PATH=/opt/ros/melodic/lib \ PATH=/opt/ros/melodic/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin \ PWD=/proc/self/cwd \ bazel/toolchain/aarch64-none-linux-gnu/wrappers/aarch64-none-linux-gnu-gcc @bazel-out/aarch64-dbg/bin/examples/hello_world/hello_world-2.params) # Configuration: e23aa3bce872abfb8f06c09952a42b5c1c7714b1c55b5bf022d91a6582852828 # Execution platform: @local_config_platform//:host Target //examples/hello_world:hello_world up-to-date: bazel-bin/examples/hello_world/hello_world INFO: Elapsed time: 5.316s, Critical Path: 1.37s INFO: 6 processes: 4 internal, 2 linux-sandbox. INFO: Build completed successfully, 6 total actions
说明:
--config=tda4指定TDA4交叉编译工具链;生成的可执行文件含.debug_info段(大小0x288),--fission=no为默认值,添加后无变化。
编译产物验证
检查可执行文件属性:
$ file bazel-bin/examples/hello_world/hello_world bazel-bin/examples/hello_world/hello_world: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, with debug_info, not stripped
查看调试段信息:
$ readelf -WS bazel-bin/examples/hello_world/hello_world |grep -E "Address|debug" [Nr] Name Type Address Off Size ES Flg Lk Inf Al [26] .debug_aranges PROGBITS 0000000000000000 0010c0 000110 00 0 0 16 [27] .debug_info PROGBITS 0000000000000000 0011d0 000288 00 0 0 1 [28] .debug_abbrev PROGBITS 0000000000000000 001458 00019c 00 0 0 1 [29] .debug_line PROGBITS 0000000000000000 0015f4 0002d3 00 0 0 1 [30] .debug_str PROGBITS 0000000000000000 0018c7 000338 01 MS 0 0 1 [31] .debug_loc PROGBITS 0000000000000000 001bff 00019b 00 0 0 1 [32] .debug_ranges PROGBITS 0000000000000000 001da0 0000c0 00 0 0 16
目标设备调试问题
将可执行文件和源码目录拷贝到设备/app/bin后,GDB调试无法关联源码:
$ gdb hello_world Reading symbols from hello_world... (gdb) set directories /app/bin/examples/hello_world (gdb) shell cat -n /app/bin/examples/hello_world/hello_world.cpp |tail -10 5 int fun(int a, int b) 6 { 7 return a+b; 8 } 9 int main(int argc, char *argv[]) { 10 std::cout << "WITH LINUX~~~" << std::endl; 11 int c=fun(1,1); 12 std::cout << "Hello World!" << std::endl; 13 std::cout<<c<<std::endl; 14 return 0; 15 } (gdb) b hello_world.cpp:10 No source file named hello_world.cpp. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (hello_world.cpp:10) pending. (gdb) b hello_world.cpp:11 No source file named hello_world.cpp. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 2 (hello_world.cpp:11) pending. (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y <PENDING> hello_world.cpp:10 2 breakpoint keep y <PENDING> hello_world.cpp:11 (gdb) r Starting program: /app/bin/hello_world WITH LINUX~~~ Hello World! 2 [Inferior 1 (process 17279) exited normally]
断点处于pending状态无法触发,程序直接正常退出。
解决方法
查看调试信息中的源码路径
执行readelf -w bazel-bin/examples/hello_world/hello_world | grep -E "file:|name:",会发现Bazel编译时记录的是构建沙箱内的绝对路径(如/home/wss/.cache/bazel/.../execroot/com_minieye_aiplorer/examples/hello_world/main.cpp),而非相对路径的hello_world.cpp。修改Bazel编译配置,生成相对路径调试信息
在BUILD文件中添加编译选项,将沙箱路径替换为相对路径:cc_binary( name = "hello_world", srcs = ["hello_world.cpp"], copts = ["-fdebug-prefix-map=$(execroot)=."], )也可以在编译命令中添加参数:
--copt=-fdebug-prefix-map=$(bazel info execution_root)=.在GDB中设置路径映射
无需修改编译配置,直接在GDB中映射沙箱路径到设备源码路径:(gdb) set substitute-path /home/wss/.cache/bazel/_bazel_wss/4112892ab2eb09dee5980f588ac10e42/execroot/com_minieye_aiplorer /app/bin映射完成后即可正常设置断点关联源码。
确认GDB版本兼容性
确保设备上的GDB版本与交叉编译工具链的GDB版本匹配,避免版本差异导致调试信息解析失败。
内容的提问来源于stack exchange,提问作者wssbygone

