问题
如果能够从主机进行编译和运行,则可以设置并达到断点,但是如果我从docker容器中执行此操作,则gdb不会达到设置的断点。
复制步骤(所有片段均已准备好复制粘贴)
创建一个docker文件:
cat << EOF > Dockerfile FROM ubuntu RUN apt-get update RUN apt-get install -y build-essential gdb EOF
构建图像并在其中运行交互式会话:
docker build -t gdb_problem_testing . && docker run --rm -it gdb_problem_testing bash
从容器内部创建小的main.cpp,编译并运行gdb:
cat <<EOF > main.cpp && g++ -g main.cpp && gdb -ex 'break 5' -ex 'run' ./a.out #include <iostream> int main(int argc, const char *argv[]) { std::cout << "hi\n"; return 0; } EOF
观察gdb的输出:
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 [Skipped gdb greeting] Reading symbols from ./a.out...done. Breakpoint 1 at 0x40078c: file main.cpp, line 5. 1 #include <iostream> 2 3 int main(int argc, const char *argv[]) 4 { 5 std::cout << "hi\n"; 6 return 0; 7 } Starting program: /a.out hi During startup program exited normally. (gdb)
从输出中可以看到,尽管程序已执行(打印为“ hi”)并成功退出,但未命中断点。我猜这里最重要的事情是程序确实运行了,并且 在启动程序正常退出期间 的消息是异常行为(根据GDB忽略了我的断点)
题
是什么阻止了gdb设置断点以及如何解决此问题?
到目前为止我尝试过的
作为建议在这里,我试图改变在一条线上/etc/apparmor.d/docker(我做到了,在主持人):替代profile docker-default flags=(attach_disconnected,mediate_deleted) {的profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {。然后运行docker容器,编译和gdb。结果是相同的:During startup program exited normally。
/etc/apparmor.d/docker
profile docker-default flags=(attach_disconnected,mediate_deleted) {
profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {
During startup program exited normally
根据另一个答案的建议,我尝试从容器中执行操作strace -f -o syscall.txt gdb ./a.out,但是出现以下错误:
strace -f -o syscall.txt gdb ./a.out
strace: test_ptrace_setoptions_followfork: PTRACE_TRACEME doesn't work: Permission denied
strace: test_ptrace_setoptions_followfork: unexpected exit status 1
但我不知道该如何解决。我尝试以root用户身份启动容器:sudo docker run --rm -it gdb_problem_testing bash然后尝试strace -这给了我同样的错误。我必须承认,我不了解docker如何管理用户权限,即容器内部的根拥有哪些用户权限,以及它是从谁那里继承权限的(从docker守护程序?)。由于我能够达到断点,因此在主机中运行gdb时,我怀疑我的问题归结为用户权限,但我不知道该如何处理。
sudo docker run --rm -it gdb_problem_testing bash
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
tldr; 采用
docker run --privileged
更长一点:我在docker中使用gdb遇到了一些问题 -–它试图(并且失败)禁用地址空间布局随机化 -–但仅在docker-machine本地Linux主机上,而不是在上。
docker-machine
当gdb无法禁用ASLR时,我所有的断点都将被忽略。使用--privileged标志修复了我的问题。你的旅费可能会改变。
--privileged