set substitute-path 是为解决GDB因调试信息中记录绝对路径(如 /home/build/src/main.c)而找不到本地实际源码(如 /home/dev/src/main.c)的核心方案;需先用 readelf -p .debug_str bin | grep "^/" 确认路径类型,绝对路径必用该命令,相对路径则应改用 dir。

直接说结论:用 set substitute-path 是为了解决「GDB 找不到源码」的核心问题——当二进制里记录的是绝对路径(比如 /home/build/src/main.c),而你本地源码实际在 /home/dev/src/main.c 时,它就是最有效的路径映射方案。
怎么判断该不该用 set substitute-path
别猜,先确认 debug info 里存的到底是绝对路径还是相对路径:
- 运行
readelf -p .debug_str your_binary | grep "/",如果输出大量以/开头的路径(如/home/xxx/src/foo.cpp),说明是绝对路径 → 必须用set substitute-path - 如果
list命令报错显示的是./src/foo.cpp: 没有那个文件或目录,那就是相对路径 → 改用dir /your/actual/src更合适 -
show directories能看到当前dir设置是否生效;show substitute-path则列出所有已注册的替换规则
set substitute-path 的写法和常见错误
语法很简单:set substitute-path <from> <to>,但顺序和末尾斜杠极易出错:
- 必须严格匹配前缀:如果
readelf显示路径是/home/user/project/src/main.c,那from应写成/home/user/project/(结尾带/),不是/home/user或/home/user/project -
to路径末尾也建议加/,避免拼接出错(比如/home/dev/project/src/main.c) - 不能嵌套使用:一次只替换一个前缀;多个不同路径需多次执行
set substitute-path - 命令只在当前 GDB 会话生效;要持久化,得写进
~/.gdbinit,例如:set substitute-path /build/ /src/
为什么有时设置了还不生效?几个关键点
常见静默失败原因不是命令写错,而是环境或权限卡住:
- 如果你的源码在 NFS、Docker 挂载卷或非标准路径下,GDB 可能因安全策略拒绝加载 —— 确保
set auto-load safe-path /已设(尤其在新版 GDB 中) -
substitute-path是字符串前缀替换,不支持通配符或正则;路径中含空格或特殊字符需用引号包裹(如set substitute-path "/home/me/my project/" "/home/me/project/") - 修改后不会自动重载源码;执行
list或layout src时才触发查找,若仍报错,再检查from是否真能完全匹配.debug_str里的原始路径 - 某些发行版预编译库(如 glibc、Qt)的调试包可能把源码放进了
/usr/src/debug/,这时更推荐用debuginfo-install(RHEL/CentOS)或apt install libc6-dbg(Debian/Ubuntu)补全,而非硬套substitute-path
最常被忽略的一点:这个命令只管“找得到”,不管“读得懂”。如果目标路径权限不足(比如 chmod 000)、文件被移动后没同步修改时间戳、或用了符号链接但 GDB 没启用 set follow-symbolic-links on,照样会静默失败。动手前先 ls -l 看一眼目标路径是否真实可访问。


















