GDB 调试
29 May 2024
Read time: 2 minute(s)
使用 JTAG 调试器连接 SoC,并通过 DebugServer 提供的 GDB 调试接口可以调试 dm-app。以
test_dm_lib 命令动态加载 hello.so
为例,整个调试过程如下所示:
-
在 GDB 中给系统函数 dlmodule_load() 打上断点:
(gdb) b dlmodule_load
-
在串口 Shell 中执行下列测试启动命令:
test_dm_lib
-
GDB 中断在 dlmodule_load() 入口以后,输入 finish 命令让 dlmodule_load() 执行完成:
(gdb) finish
-
记录串口 Shell 上打印出来的模块动态加载基地址:
test_dm_lib
动态模块的基地址会在加载函数dlmodule_load()
加载完动态模块后,打印出当前模块的基地址。例如,下列输出示例中,基地址为 0x404f8c80:01-01 10:05:30 I/NO_TAG: Module: load /sdcard/hello.so to 0x404f8c80 succeed. [AIC-DM-APP] init!
-
通过 readelf 命令读取 ELF 文件
.text
段的偏移:readelf -S hello/hello.so
输出示例如下,.text
的 Address 字段为 '0x550':Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align ... [7] .text PROGBITS 000000000000055000000550 000000000000008e 0000000000000000 AX 002 ...
-
根据已经获得的动态加载地址和
.text
段偏移,使用下列公式计算出add-symbol-file hello.so xxx
的基地址:0x404f8c80 + 0x550 = 0x404F91D0
计算出
.text
的动态基地址为 0x404F91D0, -
使用 add-symbol-file 命令在 GDB 中加载 hello.so 符号表:
(gdb) add-symbol-file aic-dm-apps/hello/hello.so 0x404F91D0
GDB 就会根据给定的基地址加载 hello.so 的符号表。
-
为了能够调试动态模块,需要在编译时保留原始 ELF 文件中的调试信息,详情可查看 保留 ELF 调试信息。
-
在 GDB 中跳转到 my_thread_init() 函数,并根据需求开始调试:
(gdb) n 30 func();(gdb) s my_thread_init () at hello/rtt_api_test.c:18 18tid= rt_thread_create("tMyTask", my_thread_entry, RT_NULL
保留 ELF 调试信息
为了能够调试动态模块,需要在编译时保留原始 ELF 文件中的调试信息。
hello.mo 和 hello.so 原始 ELF 文件中含有 debug
信息,为了减少动态加载时的内存大小,需要临时注释掉 rtconfig.py 文件中的
strip 动作
M_POST_ACTION:
M_POST_ACTION = M_STRIP + ' -R .hash $TARGET\n' + M_SIZE + ' $TARGET \n'
- 如果
aic-dm-apps
位于 Luban-Lite 项目的 \bsp\artinchip\sys\dm\ 目录下,修改该目录下的 rtconfig.py 文件。 - 如果
aic-dm-apps
已从 Luban-Lite 项目中拷贝出来,则修改该文件 aic-dm-apps\tools\sdk\ 目录下的 rtconfig.py 文件。
重新运行 scons --app=hello 或者 scons --lib=hello ,编译出来的 hello.mo 或者 hello.so ELF 文件就会带 debug 调试信息。