概要
こちらの記事(低レイヤを知りたい人のためのCコンパイラ作成入門)を読んで、コンパイラについて勉強中です。
最終的にはごくごく簡単なパーサとごくごく簡単な言語を実装して、Unity上でVM的に簡単なコマンドを外部から与えられる環境が作れたらいいなーと思っております。
さて、上記記事のコンパイラ実装はC言語が使われています。
ステップバイステップで分かりやすいのですが、若干端折られている箇所があり、そこを想像で埋めて実装していたら変なエラーが出てきたのでデバッグを行う必要があり、そのためのgdbの諸々をメモっていこうと思います。
※ なので、随時更新予定。
gdbのインストール
今回、実装にあたってはアセンブラの出力とそれをアセンブルして実際に実行するまでを確認する必要があるため、WindowsでLinuxが使える環境(Windows Subsystem for Linux - WSL)を整えてから実装を開始しています。
その関係で、Visual StudioなどWindows側で実装が行えず、サブシステムを利用しているのでgdb自体も別途インストールしました。
gdbのTUIモードをオンのものをインストールする
TUIモードとは、Text User Interfaceの略で、以下のような見た目のgdbを起動することができます。

最初、gdbのサイトから最新版を落としてきてインストールしたのですが、いわゆるIDEのように、ブレークした箇所を追いながら見ていくモード(TUI Mode)がオンにできず、結局以下の記事を参考にして改めてインストールしたところ無事に動作させることができました。
回答に書かれている内容を引用させてもらうと、以下のように実行することでインストールすることができます。
$ apt-get build-dep gdb
$ apt-get source gdb
$ cd gdb-7.7.1 # 適宜、DLされたバージョンに置き換えてください
$ ./configure --enable-tui=yes
$ make
# grab a coffee
$ sudo make install
全然関係ないけど、英語のこういうコメント好きw(# grab a coffee)
さらに、そのままインストールすると以下のようなエラーが出てしまいました。
You must put some 'source' URIs in your sources.list
以下の記事を参考に、aptをupdateしたら無事にインストールできるようになりました。
$ sudo su -c "grep '^deb ' /etc/apt/sources.list | \
sed 's/^deb/deb-src/g' > /etc/apt/sources.list.d/deb-src.list"
$ sudo apt update -y
いちおうメモ
基本的には上で紹介した記事を参考にインストールできると思いますが、自分が最初に参考にした記事もメモのため残しておこうと思います。
インストールについては以下の記事を参考にさせていただきました。
また、WSL自体のセットアップはこちらを参考にさせていただきました。
デバッグ情報込みでコンパイルする
gccなど、C言語をコンパイルする際にデバッグ可能な情報を付与した状態でコンパイルしないとデバッグが行えません。
gccでは以下のようにすることでデバッグ用の情報(シンボル情報など)を付与してコンパイルします。
$ gcc -g -O0 hoge.c
これで、デバッグ情報付きのa.outファイルが生成されるので、これをgdbから実行してやることでデバッグが可能となります。
gdbからアプリを実行する
gdbからアプリを実行するには以下のように実行します。
$ gdb a.out
ここのa.outはコンパイルされた実行ファイルを指定します。(gccではファイル名を指定しないとa.outという名前でファイルが生成される)
また、冒頭で紹介したTUIモードをオンにして起動する場合は引数-tuiを付与して実行します。
$ gdb -tui a.out
試しに、参考にさせていただいているコンパイラ(9cc)のデバッグを実行してみると以下のようになります。
# a.outが生成される
$ gcc -g -O0 9cc.c
$ gdb -tui a.out
この状態でブレークポイントを設定し、
(gdb) b main
実際に実行すると、
(gdb) run '(1+2)'
main関数でbreakするのが分かります。
あとは、下で紹介するコマンドを利用して1行(あるいは関数ごと)に、つまりIDEで普段見るような形でデバッグを続けることができます。
gdbコマンド集
gdbでは以下のコマンドを利用してステップ実行や、現在の変数の状態確認などを行っていきます。
ブレイク関連
| コマンド | 説明 |
|---|---|
| b [関数名] | [関数名]に対してブレイクポイントを貼る |
| b [ファイル名]:[行数] | デバッグ対象Cファイルの、[行数]位置にブレイクポイントを貼る |
| w [変数名] | [変数名]にウォッチポイントを設定 |
| i b | ブレイクポイント一覧を表示 |
| d [no] | 番号に対応するブレイクポイントを削除 |
実行関連
| コマンド | 説明 |
|---|---|
| n | ステップ実行(1行ずつ実行。stepover) |
| s | ステップ実行(1行ずつ実行。stepin) |
| c | 次のブレイクポイントまで処理を実行 |
| f | 現在の関数を抜けるまで処理を実行 |
| u | 現在のループを抜けるまで処理を実行 |

