Pythonでgdbを操作する。

#概要
ここでは、Pythonによるgdb操作の概要および、gdbによるPythonスクリプトのデバッグの概要について説明する。これは、Google Colabでも使える。
## gdbをPythonで操作する
gdbをPythonスクリプトで操作することが出来る。以下に操作例を示す。ここでは、catコマンドを操作するcat.pyというPythonスクリプトファイルでgdbを操作する。

```bash
gdb -x cat.py
```

cat.pyというスクリプトを以下のように定義する。ここでは、Google Colabでも使えるように、`%%writefile`から記載しているが、通常利用の場合はここを消せばよい。なお、`import gdb`は、gdb内で動かすスクリプト限定なので、gdb内で動作しているかの確認に使える。エラーが出た場合、外部スクリプトとして使っているのでエラー終了となる。
また、gdb.executeの出力は、string指定が出来るのでこれを利用して、ファイルに出力できる。

```
%%writefile cat.py
import gdb

gdb.execute('file /bin/cat')
o = gdb.execute('disassemble exit', to_string=True)
print(o)
gdb.execute('quit')
```
breakpointを設定するなら、こんな感じになる。(Pythonスクリプトをデバッグする例)

```
import gdb

gdb.execute("file python3")
gdb.execute("set pagination off")
gdb.Breakpoint("xxxxxx.cpp:136")
gdb.execute("run test.py")
for i in range(1010):
    gdb.execute("bt")
    gdb.execute("continue")

```


なお、cuda-gdbもgdbの拡張版なので、同じスクリプトが、そのまま動く。ただし、cuda部分もデバッグできるので同じPythonスクリプトで分析してもその分遅くなる。ただし、cuda-gdbでは、Pythonスクリプトのデバッギング機能である`py-xx系`コマンドは動かなかった。

##Pythonスクリプトをgdbでデバッグする
`gdb python3`と実行すると該当コマンドが利用できる。ただし、gdb7(2009年リリース)から使える機能であるが、それをベースにしているcuda-gdbでは動かなかった。

- py-list (該当範囲のPythonコード出力)
- py-bt   (該当Pythonコードのバックトレース)
- py-up   (Pythonスタックの上へ)
- py-down (Pythonスタックの下へ)
- py-print (Pythonスタックの変数表示)
- py-locals (Pythonスタックの変数リスト表示)

など

## Google Colabについて
### gdbのインストール
Colabでは、gdbがデフォルトではインストールされていない。このため以下のコマンド実行が必要である。

```
!apt install gdb python3-dbg
```
なお、一般的なDocker等のコンテナの場合、PTRACEがデフォルトでは不可なので、gdbをそのままでは利用できない。このため、設定を確認する必要がある。

### cuda-gdbの問題
(2019/08/28更新本障害は修正された)[cuda-gdb internal-error caused on google colab #5](https://github.com/NVIDIA/cuda-gdb/issues/5)

Colabは、コンテナで動いているためgdb/cuda-gdbの場合、`[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]`とシステムコールが失敗するが、それなりに動く。
ただし、cuda-gdbは、ブレークポイントを設定して動かすと止まることがある。

```
cuda-gdb/7.12/gdb/block.c:456: internal-error: set_block_compunit_symtab: Assertion `gb->compunit_symtab == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n

This is a bug, please report it.  For instructions, see:
<http://www.gnu.org/software/gdb/bugs/>.

cuda-gdb/7.12/gdb/block.c:456: internal-error: set_block_compunit_symtab: Assertion `gb->compunit_symtab == NULL' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
```

#参考資料
## gdbのリファレンス
- [23.2 Extending GDB using Python](https://sourceware.org/gdb/onlinedocs/gdb/Python.html#Python)(Pythonでgdbを操作する場合)
  - [23.2.2 Python API](https://sourceware.org/gdb/onlinedocs/gdb/Python-API.html#Python-API)
  - [23.2.4 Python modules](https://sourceware.org/gdb/onlinedocs/gdb/Python-modules.html#Python-modules)
- [5 Stopping and Continuing](https://sourceware.org/gdb/onlinedocs/gdb/Stopping.html#Stopping)(スクリプトで、yes/noの応答を指定する)
   - [5.1.1 Setting Breakpoints](https://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html)
- [22 Controlling GDB](https://sourceware.org/gdb/onlinedocs/gdb/Controlling-GDB.html#Controlling-GDB)(画面のフロー等の設定)
  - [22.4 Screen Size](https://sourceware.org/gdb/onlinedocs/gdb/Screen-Size.html#Screen-Size)

## Pythonマニュアル

- [22. gdb Support¶](https://devguide.python.org/gdb/)
  - Pythonスクリプトをgdbでデバッグする場合

##その他
- [(NVIDIA)CUDA-GDB](https://docs.nvidia.com/cuda/cuda-gdb/index.html)
  - [Debugging Your CUDA Applications
With CUDA-GDB](http://developer.download.nvidia.com/GTC/PDF/1062_Satoor.pdf) (GTCでのチュートリアル)
  - [NVIDIA/cuda-gdb](https://github.com/NVIDIA/cuda-gdb)　(cuda-gdbのソースコード)
  - [(NVIDIA Forum)Debugger for python & C/C++ CUDA](https://devtalk.nvidia.com/default/topic/1044724/cuda-programming-and-performance/debugger-for-python-amp-c-c-cuda/) (cuda-gdbは、Pythonで操作は出来る。)
- さまざまな記事
  - [Python scripts for GDB](https://medium.com/@tarun27sh/python-scripts-for-gdb-9b17ca090ac5)
     - 関数呼び出しグラフ(コールグラフ)のコード等も記載 
  - [how to set breakpoint on function in a shared library which has not been loaded in gdb](https://stackoverflow.com/questions/2642983/how-to-set-breakpoint-on-function-in-a-shared-library-which-has-not-been-loaded)
     - 共有ライブラリは動的にロード・アンロードされるため。簡単には指定できない。ファイル名に指定する必要がある。(このため、デバッグフラグでコンパイルしたライブラリでしか、関数指定できない。)
  - [How to import 'GDB' in Python](https://stackoverflow.com/questions/4792483/how-to-import-gdb-in-python)
     - `import gdb`は、gdb内のスクリプトでしか使えない。また、gdb内のスクリプトでは、デフォルトでgdb想定されており、該当行は必須ではない。とはいえ、gdb内で動いているかの確認フラグとして利用できる。
     - 外部から`import gdb`でgdbを呼び出すこともできない。
- [(PyTorch)CUDA Development tips](https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md#cuda-development-tips)