调试指定自定义动态加载器的程序时,GDB无法设置断点如何解决?
调试指定自定义动态加载器的可执行文件时,让GDB识别加载器符号的方法
你遇到的问题核心是GDB默认仅加载主程序./a的符号,而自定义动态加载器是由内核在程序启动早期加载的,GDB还未自动读取它的符号,导致无法直接设置断点。以下是符合你需求的调试方法:
方法一:启动初期手动加载加载器符号
这个方法能完全模拟内核通过.interp段加载的流程进行调试:
- 启动GDB并加载主程序:
gdb ./a
- 执行
starti命令,让程序停在初始执行的第一条指令(也就是自定义加载器的入口处,此时加载器已被内核加载到内存):
(gdb) starti
- 查看加载器在内存中的基地址:
(gdb) info proc mappings
在输出中找到你的自定义加载器(比如lib/ld-ciabatta.so)对应的行,记录其起始地址(类似0x7ffff7fdd000这样的十六进制值)。
- 手动加载加载器的符号文件,替换
<基地址>为上一步查到的地址:
(gdb) add-symbol-file lib/ld-ciabatta.so <基地址>
- 现在就能正常设置加载器内的断点了:
(gdb) b ld_stage1_entry Breakpoint 1 at 0x7ffff7fdd123: file ld/entry.c, line 45.
方法二:利用GDB的共享库加载事件断点
如果需要跟踪加载器的整个加载过程,可以开启共享库加载事件停止:
- 启动GDB后先执行:
(gdb) set stop-on-solib-events 1
- 运行程序,GDB会在每次加载共享库时暂停,此时加载器被加载后会停下,再执行
add-symbol-file加载符号,后续就能设置断点调试。
补充说明
直接用gdb ./ld.so ./a调试的差异在于:此时加载器是作为主程序被GDB启动的,内核传递的启动参数、环境变量处理逻辑和.interp段加载的场景存在区别,而上面的方法完全模拟了内核加载加载器的真实流程,更符合你的调试需求。
内容的提问来源于stack exchange,提问作者bumbread
相关产品推荐
相关产品推荐

