gdbデバッガを使う


[東京高専プロコンゼミ① Advent Calendar 2022
](https://adventar.org/calendars/8370)の8日目の記事です．ほかの記事もぜひご覧ください．

# gdb
linux に標準のデバッガ．
入ってない場合`debian`の場合は以下のコマンドで入る．
```
$ sudo apt install gdb
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/b5aeb89a-6432-b2bf-82d5-084c2e69a3f0.png)
上の画像は`gdb-peda`というgdbを拡張するスクリプトを入れたもの．
素のgdbはちょっと使いづらいと思うのでこの`gdb-peda`のような拡張を使うと良いと思う．
[gdb-peda](https://github.com/longld/peda)
```
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit
```
セットアップは以上のコマンドを実行するだけで良い．

またCopyrightが邪魔な場合は`gdb -q`で起動すると表示されない．なのでこの`alias`を張ると良い．
```sh:bashを使っている場合
echo 'alias gdb="gdb -q"' >> ~/.bashrc 
```
```sh:zshを使っている場合
echo 'alias gdb="gdb -q"' >> ~/.zshrc 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/4a4bc339-b620-2b34-4e7d-1d2384f73f34.png)


いろいろ説明を書きますが、以下のページを見ればだいたいわかります．

https://flex.phys.tohoku.ac.jp/texi/gdb-j/gdb-j_toc.html

# デバッグ用にコンパイル
```:デバッグ用にコンパイル
$ gcc -g -o <output> <intput.c>
```

`-g`をつけてコンパイルするとデバッグ用の情報を含めてくれるのでデバッグ時にいろいろ便利．
**(つけなくてもデバッグできる)**


# 起動

```:起動
$ gdb <実行形式ファイル>
```


# break
`break`または`b`で break pointを設定できる．
mainにbreak point を張る例
```:シンボルでbreak
b main
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/e58f194d-521b-e716-4498-0364620078ee.png)

```:アドレスでbreak
b *0x555555555140
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/be5c5d9a-e190-8a51-cf2f-7eabbd4e9a52.png)

# run
実行するには`run`または`r`を入力．
```:gdb
run
```

peda実行した結果．ブレークポイントを仕掛けていた場合そこで停止する．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/430dfbf8-0a5a-7626-5864-70554c947c04.png)

`peda`を入れている場合上から
- レジスタの状態．
- 今実行している命令．
- スタックの状態．
- 対応するプログラム行（`-g`付きでコンパイルした場合）
が表示される．

# x (メモリの確認
xで指定したアドレスから指定した分だけ表示することができる．
下は10個の`i(instruction)`を`0x555555555139`から表示する例．
```:gdb
x /10i 0x555555555139
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/71bcd022-9742-40c3-b848-2b1d5fd0f4c2.png)

xで表示できる形式は以下のページを参照．

https://www.cism.ucl.ac.be/Services/Formations/ICS/ics_2013.0.028/composer_xe_2013/Documentation/ja_JP/debugger/cl/GUID-59A7666A-77E7-46B0-AA0B-6507CD94DE64.htm

# reg (レジスタの表示
レジスタファイルの状態を表示．
```:gdb
reg
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/ced5e690-e78a-2a2a-0148-19523e2e3792.png)

# xinfo register
指定したレジスタの値を見る．
```:gdb
xinfo register <register>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/5d299790-79a7-587b-97f4-b9078de595e1.png)

# set (メモリ,レジスタ書き換え
メモリやレジスタの書き換えができる．

下のは`0x555555555139`に1をエンディアンに従い書きこむ例．
```:gdb
set *0x555555555139=1
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/7b5901b6-3ce8-1165-8dbf-ddda30d72f0a.png)

以下は`rax`に`0`を書き込む例
```:gdb
set $rax=0x1623475869
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/928b7a94-9ea5-858b-e0ff-abe6854e80ab.png)

# c
`continue`.プログラムの再開．
```
c
```
# n
`next`
命令を一つ進める．
```
n
```
# s
`step`
命令を一つ進める．サブルーチンの中に入る．（`call`命令で呼ばれている関数の中に入る．`n`は入らない．

```
s
```

# q (終了
`gdb`を終了
```
q
```

# 直前のコマンドと同じコマンド
何も入力せず`Enterキー`を押すことで直前に実行したコマンドをもう一度実行できる．
`step`とか`next`でプログラムを進めたいときに便利．

# おわりに
間違いがあったら教えてください．
[東京高専プロコンゼミ① Advent Calendar 2022
](https://adventar.org/calendars/8370)の8日目の記事です．ほかの記事もぜひご覧ください．

https://flex.phys.tohoku.ac.jp/texi/gdb-j/gdb-j_toc.html