首页 > 解决方案 > docker 容器中的可执行文件不会从 gdb 远程调试中注册断点

问题描述

远程设置

我需要调试一个复杂的 C++ 程序,该程序安装在由 Kubernetes 控制的 docker 容器中。docker 容器还提供了一个 gdbserver 并暴露了容器端口 44444。

主机设置

控制和检查程序的 gdb 部分设置在另一个 docker 容器中。这是因为 SUSE 环境仅在此容器中可用,而不是在 VM Box 中的我的 Ubuntu 18.04 机器上。

本地调试效果很好

在 SUSE docker 容器中本地调试程序效果很好。程序在指定的断点处停止,这些断点也在远程调试中指定。所有断点都单独定义在程序的基本源代码文件中,而不是任何库中。

已验证,远程 docker 容器中的可执行文件与主机容器中的可执行文件相同;它已使用调试符号和非优化代码 (-ggdb -O0) 进行编译。

问题

远程调试程序只缺少在主机上定义的断点处停止。容器中的程序在后台启动。当 gdbserver 附加它的 process_id 时,程序会暂停,直到在 gdb 主机会话中发出“继续”并转发到远程容器中的 gdbserver。

该程序部署了基本的 C++ 类文件和共享程序库以及共享项目库。它以参数启动并在作业完成后退出。

当程序启动时,它会读取配置文件、连接到数据库、读取数据库条目、准备数据并将其格式化为 XML 格式的条目,并将它们写入输出文件。

HelloWorld 远程调试测试效果很好

为了验证通过 gdbserver 端口的远程调试设置和连接是否正常工作,我创建了一个简单的 HelloWorld C++ 程序并将其复制到同一个远程 docker 容器中并测试其中的断点行为。

当 HelloWorld 程序在容器中运行时,远程调试测试场景运行成功:

目标程序远程调试不会在断点处停止

当容器中的目标 C++ 程序使用相同的场景进行调试时,它不会在定义的断点处停止:

在定义的断点处停止的 docker 容器中进行远程调试时,我缺少什么?

标签: c++dockergdbremote-debugginggdbserver

解决方案


由于 Ubuntu(版本 >= 10.10)中的安全性增强,不允许用户对不是调试器后代的进程进行 ptrace。
默认情况下,进程 A 无法跟踪正在运行的进程 B,除非 B 是 A 的直接子级(或 A 以 root 身份运行)。
仍然始终允许直接调试,例如gdb EXEand strace EXE

可以通过将值/proc/sys/kernel/yama/ptrace_scope从 1(=默认)更改为 0(=所有进程允许跟踪)来放松限制。可以通过以下方式更改安全设置:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

HelloWorld 远程调试测试效果很好

HelloWorld 容器中的远程调试是怎么发生的?
HelloWorld 容器是USER userName在 Dockerfile 中创建的,该用户名与登录到 Ubuntu 的用户名相同。
用于部署开发容器(使用要调试的 C++ 程序)的 Dockerfile 定义了与我的 Ubuntu 登录中使用的不同的用户名和组名。

ptrace 范围描述的所有学分都属于以下帖子,请参阅 Eliah Kagan 的第二个回答 - 感谢您的详尽解释!- 这里:
https ://askubuntu.com/questions/143561/why-wont-strace-gdb-attach-to-a-process-even-though-im-root


推荐阅读