当我从Docker容器内部运行时,gdb不会触发任何断点 [英] gdb does not hit any breakpoints when I run it from inside Docker container

查看:678
本文介绍了当我从Docker容器内部运行时,gdb不会触发任何断点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题



如果我从主机编译并运行,我可以设置和达到断点,但如果我这样做从Docker容器中,gdb不会触发设置的断点。



重现步骤(所有片段都可以复制粘贴) / p>

创建一个docker文件:

  cat< EOF> Dockerfile 
FROM ubuntu
运行apt-get update
运行apt-get install -y build-essential gdb
EOF

构建图像并在其中运行交互式会话:

  docker build -t gdb_problem_testing。 &&& docker运行--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<< 嗨
return 0;
}
EOF

观察gdb输出:

  GNU gdb(Ubuntu 7.7.1-0ubuntu5〜14.04.2)7.7.1 
[Skipped gdb greeting]
读取符号来自./a.out...done。
断点1在0x40078c:文件main.cpp,第5行
1 #include< iostream>
2
3 int main(int argc,const char * argv [])
4 {
5 std :: cout<<< 嗨
6返回0;
7}
启动程序:/a.out
hi
启动程序正常退出。
(gdb)

从输出可以看到断点没有被击中,程序被执行(打印嗨)并成功退出。我想这里最重要的是程序运行,消息启动程序正常退出是一个异常行为(根据 GDB忽略我的断点



问题



什么是阻止gdb设置断点和如何解决这个问题?



我迄今为止所尝试的


  1. 根据建议这里,我试图在 /etc/apparmor.d/docker (我在主机中)中更改了一行:
    替换 profile docker-default flags =(attach_disconnected,mediate_deleted){ by profile docker-default flags =(attach_disconnected,mediate_deleted,complain){。然后运行docker容器,compile和gdb。结果是一样的:启动程序正常退出


  2. 另一个答案,从容器内,我试图做 strace -f -o syscall .txt gdb ./a.out ,但是我收到以下错误:

      strace:test_ptrace_setoptions_followfork :PTRACE_TRACEME不起作用:权限被拒绝
    strace:test_ptrace_setoptions_followfork:意外退出状态1

    但我不明白如何工作。我尝试以root身份启动容器: sudo docker运行--rm -it gdb_problem_testing bash 然后尝试strace - 这给了我一样的错误。我必须承认我不明白Docker管理的用户权限,即容器中的根目录是什么用户权限,以及从哪里继承权限(从docker守护程序?)。由于我能够打破断点,当我在主机中运行gdb时,我怀疑我的问题会归结为用户权限,但我不知道如何处理。


  3. 在主机中我尝试做 echo 0 | sudo tee / proc / sys / kernel / yama / ptrace_scope 根据建议,另一个答案



解决方案

tldr ;使用

  docker run --privileged 

更长的时间:我有一些在Docker中的gdb问题 ---尝试(和失败)禁用地址空间布局随机化 ---但仅在 docker-machine ,而不是我的本机linux主机。



当gdb无法禁用ASLR时,我的所有断点都将被忽略。使用 - 特权标志修复了我的问题。您的里程可能有所不同。


The problem

I am able to set and reach a breakpoint if I compile and run from the host, but if I do it from within the docker container gdb does not hit the breakpoints that were set.

Steps to reproduce (all snippets are copy-paste ready)

Create a docker file:

cat << EOF > Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get install -y build-essential gdb
EOF

Build an image and run an interactive session in it:

docker build -t gdb_problem_testing . && docker run --rm -it  gdb_problem_testing bash

From inside of the container create small main.cpp, compile, and run 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

Observe the gdb output:

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) 

From the output one can see that the breakpoint was not hit, although the program was executed (printed 'hi') and exited successfully. I guess the most important thing here is that the program did run and that the message During startup program exited normally is an anomalous behavior (according to GDB ignores my breakpoints )

Question

What is preventing gdb from setting the breakpoint and how to fix this?

What I tried so far

  1. As suggested here, I tried to change a line in /etc/apparmor.d/docker (I did it in the host): substitute profile docker-default flags=(attach_disconnected,mediate_deleted) { by profile docker-default flags=(attach_disconnected,mediate_deleted,complain) {. Then run the docker container, compile, and gdb. The result was the same: During startup program exited normally.

  2. As suggested in another answer, from within the container, I tried to do strace -f -o syscall.txt gdb ./a.out, but I get the following error:

    strace: test_ptrace_setoptions_followfork: PTRACE_TRACEME doesn't work: Permission denied
    strace: test_ptrace_setoptions_followfork: unexpected exit status 1
    

    but I do not understand how to work this around. I tried to start the container as root: sudo docker run --rm -it gdb_problem_testing bash and then tried the strace -- this gave me the same error. I must admit I do not understand how the user privileges are managed by the docker, i.e. what user rights the root inside of the container has and from whom does it inherit the rights (from the docker daemon?). Since I able to hit the breakpoint, when I run gdb in the host, I suspect that my problem would boil down to the user rights, but I do not know how to approach it.

  3. In the host I tried to do echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope as suggested in yet another answer.

解决方案

tldr; use

docker run --privileged

Longer: I was having some problems with gdb in docker---it was attempting (and failing) to disable address space layout randomization---but only on docker-machine, not on my native linux host.

When gdb failed to disable ASLR, all of my breakpoints would be ignored. Using the --privileged flag fixed my issue. Your mileage may vary.

这篇关于当我从Docker容器内部运行时,gdb不会触发任何断点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆