根本原因是gdb调试信息中记录的源码绝对路径与本地实际路径不匹配;需用set substitute-path重映射路径前缀,或用dir添加搜索路径,其中substitute-path在符号解析阶段生效,优先级高于dir。

gdb 调试时提示“no source file”或“Source file not found”
根本原因是 GDB 找不到与远程程序符号匹配的源码路径。它加载了 ./program 的调试信息(含文件名、行号),但没在本地磁盘上找到对应路径下的 main.c 或 utils.h 等文件。
常见错误现象包括:
– list 命令报错 “No such file or directory”
– break main.c:10 失败,提示无法解析位置
– TUI 模式(Ctrl+X+A)只显示汇编,不显示源码窗口
- 确认远程程序是带
-g编译的,且未被strip—— 用file ./program检查是否含 “with debug_info” - 确保本地 GDB 加载的可执行文件和远程运行的完全一致(校验
md5sum或sha256sum) - 用
info sources查看 GDB 认为该程序“应该从哪些路径读源码”,比如输出可能含/home/dev/project/src/main.c - 用
dir /path/to/your/src把本地源码根目录加进搜索路径(可多次调用,路径按顺序尝试) - 如果源码不在标准路径,又不想改
dir,可用set substitute-path /build/path /local/path重映射路径前缀
target remote 连接后怎么让 gdb 找到源码
连接成功(target remote 192.168.0.19:2345)只是建立了控制通道,GDB 仍需本地源码才能做源码级调试。它不会自动拉取远程文件,也不解析远程 /proc/pid/cwd。
典型使用场景:嵌入式开发中,代码在 Ubuntu 主机写,交叉编译后推到 ARM 板运行;板子上只有二进制,没有源码。
- 不要依赖
gdbserver传源码 —— 它不传输任何源文件 - 避免把源码放在 NFS 或远程挂载路径下 —— GDB 不会自动识别挂载点变更,
dir仍需显式指定本地挂载路径 - 若项目用了 CMake + out-of-source build,确保
dir指向的是源码树(src/),不是构建目录(build/),否则#include路径会错位 - 调试多个模块时,可一次性添加多级路径:
dir src/ core/ drivers/ utils/
为什么 set substitute-path 比 dir 更可靠
当编译环境和调试环境路径结构不同时(例如 CI 构建机路径是 /jenkins/workspace/build/src/,而你本地是 ~/proj/src/),仅靠 dir 无法匹配 —— 因为 GDB 先按绝对路径查找,找不到才 fallback 到 dir 列表。
substitute-path 是在符号表路径解析阶段做字符串替换,属于更底层的路径重写机制。
- 查看当前映射:
show substitute-path - 添加映射:
set substitute-path /jenkins/workspace/build/ ~/proj/ - 注意斜杠结尾:必须严格匹配前缀,
/jenkins/≠/jenkins(后者不触发替换) - 该设置在 session 内有效,建议写入
.gdbinit避免每次重复输入
容易被忽略的细节:调试信息里的路径是绝对路径,且不可写时才 fallback
GDB 默认信任调试信息里记录的绝对路径(如 /home/user/app/src/main.c)。它先尝试打开这个路径,失败后才轮询 dir 列表。也就是说,即使你本地源码在 ~/app/src/,只要没配 substitute-path,GDB 就不会自动把 /home/user/ 替换成 ~/。
尤其要注意符号链接和 ~ 展开:GDB 不展开 ~,所以 dir ~/src 实际查的是字面量 ~/src 目录,应写成完整路径如 /home/user/src。











