前置き
自作したプログラムがコンテナの中でセグフォを起こした...そんな経験はありませんか?
コンテナ内部のcoredumpctlにはデバッグ情報が残りません.
またコンテナに特権を与えなかった場合,/proc以下のファイルはコンテナ側で操作することができず,coreファイルの出力設定も変更ができません.
そこで今回はそんな環境下でもコンテナ内部で発生したcore dumpをデバッグする手法を公開します.
やり方
結論は非常に簡単で,__ホスト側のcoredumpctlにデバッグ情報が保存__されています.
そこでホスト側のcoredumpctlを使い,コンテナから(ヴォリュームマウントなどで)取り出した実行ファイルと合わせてデバッグすればOKです.
※ coredumpctlを使わずにcoreファイルが直接吐き出される場合は,落ちたコンテナをcommitして作ったイメージをrunして中でデバッグすればOKです.
バイナリデータの取得はdocker cp
コマンドを使ってください.
何故ホスト側のcoredumpctlにデバッグ情報が?
同じようにコンテナ側でcoredumpctlがお仕事をしてくれない件がissueとして出ていました.
その中でcatrixs氏が「Because coredump is captured by kernel」と指摘しています.
実験
実験環境
環境 | 名前 |
---|---|
OS | Manjaro 18.1.3 Juhraya |
Dockerクライアント | 19.03.4-ce |
Cコンパイラ | gcc 9.2.0 |
デバッガ | gdb 8.3.1 |
手順
以下のようにsegfo_sample.c
を作成します.
#include<stdio.h>
int main() {
char* null_po = NULL;
printf("%d", *null_po);
}
コンパイルした実行ファイルをコンテナにマウントして実行しましょう.
$ gcc -g segfo_sample.c -o segfo_sample
$ docker run --rm -it -v ${PWD}/segfo_sample:/root/segfo_sample -w /root debian bash
root@f36b0603fce1:~# ./segfo_sample
Segmentation fault (core dumped)
root@f36b0603fce1:~# exit
コンテナを抜け,ホスト側でコアダンプ情報を確認しましょう.
$ coredumpctl info segfo_sample
PID: 31371 (segfo_sample)
UID: 0 (root)
GID: 0 (root)
Signal: 11 (SEGV)
Timestamp: Wed 2019-12-11 15:10:30 JST (25s ago)
Command Line: ./segfo_sample
Executable: /root/segfo_sample
Control Group: /system.slice/docker.service
Unit: docker.service
Slice: system.slice
Boot ID: 6890bb7e1fbf4346af58a455e5087c1c
Machine ID: 4ea99d5d328042c1985355191e83ab72
Hostname: cabon
Storage: /var/lib/systemd/coredump/core.segfo_sample.0.6890bb7e1fbf4346af58a455e5087c1c.31371.1576044630000000.lz4 (inaccessible)
Message: Process 31371 (segfo_sample) of user 0 dumped core.
Stack trace of thread 7:
#0 0x000055feb6c0f14d n/a (/root/segfo_sample)
#1 0x00007f05571f12e1 n/a (/lib/x86_64-linux-gnu/libc-2.24.so)
ちゃんとホスト側に情報が来ているので,PIDを指定してデバッグしちゃいましょう.
$ sudo coredumpctl debug 31371
[sudo] password for takahiro:
PID: 31371 (segfo_sample)
UID: 0 (root)
GID: 0 (root)
Signal: 11 (SEGV)
Timestamp: Wed 2019-12-11 15:10:30 JST (2min 12s ago)
...
/root/segfo_sample: No such file or directory.
[New LWP 7]
Core was generated by `./segfo_sample'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000055feb6c0f14d in ?? ()
(gdb)
あらら.../root/segfo_sample
なんて実行ファイルが無いから覗けないよ?って言われてしまいましたね...コンテナとはパスが違うので当然といえば当然ですが...
fileコマンドを使って,ホスト側に残された実行ファイルを指定しましょう.
(gdb) file segfo_sample
Reading symbols from segfo_sample...
(gdb) run
Starting program: /home/takahiro/hoge/segfo_sample
Program received signal SIGSEGV, Segmentation fault.
0x000055555555514d in main () at sample.c:5
5 printf("%d", *null_po);
(gdb) backtrace
#0 0x000055555555514d in main () at sample.c:5
いい感じです.