Docker上でGDBとQEMU(ユーザモードエミュレーション)を接続してデバッグ
目標
筆者の実機(M1 Mac, AArch64)でx86_64のDockerコンテナを立ち上げ、その上でQEMUを用いてリモートデバッグをする
手順
x86_64なDockerコンテナを起動し、コンテナに入る
docker run -it --platform linux/amd64 ubuntu:latest
qemu-user-static
gdb
及びコンパイラ含め必要なツールをインストールする
apt update apt install qemu-user-static gdb gcc vim
プログラムを書いてデバッグ情報付きでコンパイルする(a.out
はx86_64のバイナリ)
root@6fd1c6bc2337:/home# vim test.c root@6fd1c6bc2337:/home# cat test.c #include <stdio.h> int main(void) { printf("Hello World\n"); return 0; } root@6fd1c6bc2337:/home# gcc test.c -g -static root@6fd1c6bc2337:/home# ./a.out Hello World
qemu-x86_64-static
でTCPの1234ポートを開く
qemu-x86_64-static -g 1234 a.out &
gdb
でポートに接続しリモートデバッグを開始する
gdb -q -ex "target remote :1234" a.out
run
コマンドが使えないことに注意(continue
を使う)
root@6fd1c6bc2337:/home# gdb -q -ex "target remote :1234" a.out Reading symbols from a.out... Remote debugging using :1234 0x0000000000401650 in _start () (gdb) b main Breakpoint 1 at 0x40177d: file test.c, line 4. (gdb) run The "remote" target does not support "run". Try "help target" or "continue". (gdb) c Continuing. Breakpoint 1, main () at test.c:4 4 printf("Hello World\n"); (gdb) n Hello World 5 return 0;
コマンドライン引数ありの場合
root@6fd1c6bc2337:/home# vim test.c root@6fd1c6bc2337:/home# cat test.c #include <stdio.h> int main(int argc, char **argv) { for (int i = 0; i < argc; i++) { printf("%s\n", argv[i]); } return 0; } root@6fd1c6bc2337:/home# gcc test.c -g -static root@6fd1c6bc2337:/home# ./a.out aaa iii ./a.out aaa iii
qemu-x86_64-static
で実行ファイル名の後に引数を書くようにすれば良い
qemu-x86_64-static -g 1234 a.out aaa iii &
リダイレクトについても同様
qemu-x86_64-static -g 1234 a.out aaa iii > output.txt &
なぜこの記事を書いたか
AArch64であるM1 Mac上のx86_64なDockerコンテナで普通にGDBを使おうとして以下のようになりできない
root@6fd1c6bc2337:/home# gdb a.out GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from a.out... (gdb) run Starting program: /home/a.out warning: Error disabling address space randomization: Operation not permitted warning: Could not trace the inferior process. warning: ptrace: Function not implemented During startup program exited with code 127.
warning: ptrace: Function not implemented
とあるようにGDB内で使われるシステムコールptrace()が削除されている(?)ようだ。
そこで今回その代替となるQEMUが提供するリモートデバッグ機能を利用するに至った。