docker 容器中的可执行文件未注册来自 gdb 远程调试的断点

Executable in docker container does not register breakpoints from gdb remote debugging

远程设置

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

主机设置

用于控制和检查程序的 gdb 部分设置在另一个 docker 容器中。 这是由于这种情况,SUSE 环境只能在这个容器中使用, 不在我的 Ubuntu VM Box 中的 18.04 机器上。

本地调试效果很好

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

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

问题

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

该程序使用基本的 C++ class 文件和共享程序库以及共享项目库进行部署。 带参数启动,job结束后退出

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

HelloWorld远程调试测试正常

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

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

目标程序远程调试不停断点

容器中的目标C++程序在相同场景下调试时不会在定义的断点处停止:

在定义的断点处停止的 docker 容器中进行远程调试我错过了什么?

Target program remote debugging doesn't stop at breakpoints

猜测:目标程序 fork()s 并执行子进程中的大部分代码(并且您的 gdbserver 附加父进程)。

要验证这一点,请将一些 printf("%s:%d: pid=%d\n", __FILE__, __LINE__, getpid()); 调用插入目标程序中的重要位置。如果我的猜测是正确的,您应该会看到 pidmain()connect_to_database() 之间变化。

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

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

HelloWorld remote debugging test works well

HelloWorld 容器中的远程调试效果如何?
HelloWorld 容器是在 Dockerfile 中使用 USER userName 创建的 与登录 Ubuntu.
的用户名相同 用于部署开发容器(带有要调试的 C++ 程序)的 Dockerfile 定义了与我的 Ubuntu 登录中使用的不同的用户名和组名。

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