先用readelf -p .debug_str查看debug info中路径类型:若为/home/xxx.cpp等完整路径则属绝对路径,需用set substitute-path前缀替换;若为./src/x.cpp等则属相对路径,应使用dir添加搜索前缀;二者互斥,混用无效。

GDB找不到源码时,不是路径没加对,而是你没区分清楚 debug info 里存的是相对路径还是绝对路径。 用 readelf -p .debug_str 先看一眼,再决定用 dir 还是 set substitute-path —— 混用或乱试只会让 list 命令持续报 “No such file or directory”。
怎么判断 debug info 存的是相对路径还是绝对路径
直接查二进制文件的调试段,不依赖猜测:
- 运行
readelf -p .debug_str your_binary,搜索.c、.cpp或.h后缀的字符串 - 如果看到类似
/home/user/project/src/main.c这种完整路径 → 绝对路径 - 如果看到类似
../src/main.c或src/main.c→ 相对路径 - 注意:CMake 默认用绝对路径写入 debug info;手写 Makefile +
gcc -g且源码在当前目录下编译,更可能生成相对路径
绝对路径场景:用 set substitute-path 做前缀替换
dir 命令对绝对路径完全无效。必须靠字符串级替换:
- 假设
list显示/opt/build/src/log.cpp: No such file or directory - 而你的源码实际在
/home/dev/src/log.cpp,执行:set substitute-path /opt/build/ /home/dev/ - 替换规则是「从左到右最长前缀匹配」,所以
/opt/build/src→/home/dev/src,但/opt/builder不会被误替 - 查看当前规则:
show substitute-path;清空全部:set substitute-path "" - 该设置仅对本次 gdb 会话有效;如需持久化,写进
~/.gdbinit(注意:某些发行版要求先加add-auto-load-safe-path /才允许加载)
相对路径场景:用 dir 添加搜索前缀
当 readelf 确认是 ./src/main.c 或 ../lib/utils.h 这类路径时,dir 才起作用:
- 比如当前提示
./src/main.c: No such file or directory,而源码在/mnt/code/project下,就执行:dir /mnt/code/project - GDB 会把所有相对路径拼接到这个目录后查找,即
/mnt/code/project/./src/main.c→ 实际尝试/mnt/code/project/src/main.c - 支持多个路径,用冒号分隔:
dir /path/a:/path/b:/path/c - 查看已设路径:
show directories;清空:dir(不带参数) - 启动时直接指定:
gdb -d /mnt/code/project your_binary
最容易被忽略的一点:set substitute-path 和 dir 是互斥策略,不是叠加关系。选错类型,命令再多次也无效。另外,GDB 不会自动递归扫描子目录 —— 它只按你给的路径或替换结果,严格拼出一个完整路径去 open(),不存在“模糊匹配”或“就近查找”。











