唯一可靠方式是直接用gdbserver :1234 --attach <PID>附加运行中进程;需确保架构匹配、ptrace权限放开、主机GDB版本兼容、目标二进制带完整调试信息且未优化。

直接用 gdbserver --attach 附加到运行中的进程,这是唯一可靠的方式。其他方法(比如先 kill -STOP 再启动 gdbserver)会破坏进程状态,不可行。
目标机上必须用 gdbserver --attach 启动服务
不能靠“重启进程+加调试参数”来补救——你调试的是已运行的进程,它可能持有锁、打开 socket、维护状态机,中断再启会丢失上下文。
正确做法是让 gdbserver 直接 attach:
-
gdbserver :1234 --attach <PID>:监听本地端口 1234,附加到指定 PID - 必须确保
gdbserver架构与目标进程匹配(如 ARM 进程必须用arm-linux-gnueabihf-gdbserver) - 若提示
Operation not permitted,检查是否被 ptrace scope 限制:echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - 附加成功后输出类似:
Attached; pid = 1234和Listening on port 1234
target remote 连接前要确认符号和库路径
主机端用交叉 GDB(如 arm-linux-gnueabihf-gdb)连接后,file 加载的必须是带调试信息的原始可执行文件(不是 stripped 版),否则 list、break 都会失败。
常见遗漏点:
- 没设
set solib-search-path→shared library not found错误,info sharedlibrary显示大量No - 路径里混用了 build 输出目录和 rootfs 目录 → 动态库加载错位,
print变量显示<optimized out></optimized> - 没用
symbol-file补充内核模块或 dlopen 加载的 so →bt调用栈不全
附加后无法单步或断点失效?优先查三件事
这类问题几乎都源于环境错配,而不是 GDB 命令写错:
- 目标机
gdbserver --version和主机 GDB 的版本差太远(如 gdbserver 12.x + GDB 9.x)→ 协议不兼容,target remote后卡住或报Remote 'g' packet reply is too long - 进程是 multithreaded 但没开
set follow-fork-mode child→ 主线程停了,子线程继续跑,看起来“断点没生效” - 编译时用了
-O2或更高优化 → 变量被寄存器优化掉,watch失效,step跳行;必须用-O0 -g3重新编译目标二进制(哪怕只是复现问题)
真正麻烦的永远不是命令怎么输,而是目标进程的运行态、符号完整性、工具链 ABI 一致性这三者之间是否咬合得上。少一个,continue 就可能直接跑飞。


















