Edited at

gdbserverから起動したGoのプログラムをリモートデバッグしてみるとどうなるか

More than 3 years have passed since last update.

2つのDockerコンテナー間でGoのプログラムを gdb to gdbserver でリモートデバッグしてみます。

結論としては、この方法はおすすめできないです。

確認に使ったソースコードはこちら

github.comkai-zoa/golang-debug-guest-app


利用するツールと構成


  • go

  • gdb

  • gdbserver

プログラムを実行するコンテナではgdbserverでプログラムを実行し、リモートデバッグの接続を待ち受けます。

リモートデバッグするコンテナ(Dockerfile)

gdbserverからアプリケーションを実行するコンテナ(Dockerfile)

2つのコンテナをdocker-composeで起動して確認します。

# docker-compose.yml

debugger:
container_name: my_debugger
build: debugger
tty: true
volumes:
- ./bin:/go/bin
links:
- runner:runner
runner:
container_name: my_runner
build: runner
tty: true
ports:
- "9091:9091"
volumes:
- .:/go/src/github.com/kai-zoa/golang-debug-guest-app
- ./bin:/go/bin

起動します。

docker-compose build && docker-compose up -d


gdbserverからGoのプログラムを実行

内容はこんな感じ、起動すると名前の入力を求めて、挨拶する単純なコード

package main

import (
"os"
"bufio"
"fmt"
)

func main() {
var s string
scanner := bufio.NewScanner(os.Stdin)
fmt.Print("Enter Name: ")
for scanner.Scan() {
s = scanner.Text()
fmt.Printf("Hello %s!!\n", s)
fmt.Print("Enter Name: ")
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
}
}

ビルドしてgdbserver上で実行。

# デバッグビルド

$ docker exec -it my_runner go install -gcflags "-N -l" github.com/kai-zoa/golang-debug-guest-app
# gdbserverを立ち上げて起動
$ docker exec -it my_runner gdbserver localhost:9091 golang-debug-guest-app
Process golang-debug-guest-app created; pid = 24
Listening on port 9091

これでデバッグ接続の待受が開始されます。


接続してリモートデバッグしてみる

リモートデバッグ用のコンテナからgdbを起動してプロンプトでtarget remote runner:9091して接続する

$ docker exec -it my_debugger gdb golang-debug-guest-app

GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
...
...
(gdb) target remote runner:9091
Remote debugging using runner:9091
_rt0_amd64_linux () at /usr/local/go/src/runtime/rt0_linux_amd64.s:8
8 LEAQ 8(SP), SI // argv
(gdb)

接続されたっぽい…

とりあえずソースコードが見れるか確認してみる。

(gdb) l

3 // license that can be found in the LICENSE file.
4
5 #include "textflag.h"
6
7 TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8
8 LEAQ 8(SP), SI // argv
9 MOVQ 0(SP), DI // argc
10 MOVQ $main(SB), AX
11 JMP AX
12

ファッ!?

なんかアセンブラのコードが見えますね。

直接、gdbからプログラムを動かしたときと大分勝手が違うようです。

諦めましょう…


本当にやりたかったこと

普段OSX上から開発用Dockerコンテナでgoのプログラムを動かしているので、ホストOS側からデバッグできないのかなと考えて試してみました。

良いデバッグの方法があったら誰か教えてください。

メリークリスマス!