LLDBを使ってCのデバッグをする


Macの場合は最初からlldbがあるため、これを使ってデバッグすることができます。
iOSアプリの開発をしているとデバッグに`(lldb)`とコンソールに出てきますが、まさにこれです。

## デバッグの開始

まず、デバッグを開始するためには`c`ファイルを`-g`オプションを付けてデバッグ可能な状態でコンパイルしないとなりません。

```console
$ gcc -o hoge -g hoge.c
```

ちなみに`hoge.c`の中身はごく簡単にこんな感じ。

```c:hoge.c
#include <stdio.h>

int main(int argc, char **argv) {
    char *test = "This is a debug demo.";
    char *name = "edo";
    int age = 20;

    printf("Name: %s, Age: %d\n", name, age);

    return 0;
}
```

そしてこれをコンパイルすると`hoge`ファイルができるのでここからデバッグ開始です。


### ファイル名を指定してlldbを起動

lldbの起動にはいくつかあるみたいですが、一番シンプルなのはデバッグ対象のファイルを指定することでしょう。
以下のように、先ほどコンパイルしたファイルを指定して実行してみます。

```console
$ lldb hoge
(lldb) target create "hoge"
Current executable set to 'hoge' (x86_64).
(lldb)
```

すると`lldb`が起動して、コマンドを受け付ける状態になります。

### 実行してみる

現状だとまだ`lldb`が起動しただけなのでプログラムは実行されていません。
そこで、`run`（あるいは`r`）とタイプしてプログラムを実行してみます。
すると以下のようになりました。

```console
(lldb) r
Process 93882 launched: '/Path/To/hoge' (x86_64)
Name: edo, Age: 20
Process 93882 exited with status = 0 (0x00000000)
(lldb)
```

### ブレークポイントを設定する

`printf`の内容もしっかり出力されているのが分かります。
ただこれだけではなにもデバッグになりません。
次はブレークポイントを設定してみます。

```console
(lldb) br set --file hoge.c --line 6
(lldb) br set -f hoge.c -l 6
```
上記のように、ファイル名と行数を指定してブレークポイントを設定します。
*（ちなみに`br`は`breakpoint`の省略形です）*


#### 省略形でブレークポイントを張る

ちなみに以下のようにすることでもブレークポイントを張ることができます。

```console
(lldb) b hoge.c:8
```

#### 関数にブレークポイントを張る

`foo`という関数にブレークポイントを設定する場合は以下のようにします。

```console
(lldb) br set -n foo
(lldb) br set --name foo
```


-------------------------------------------

ブレークポイントを設定したあと、再度実行してみると以下のように出力され、処理が中断します。

```console
(lldb) r
Process 93890 launched: '/Path/To/hoge' (x86_64)
Process 93890 stopped
* thread #1: tid = 0x53c0ae, 0x0000000100000f23 hoge`main(argc=1, argv=0x00007fff5fbff460) + 51 at hoge.c:6, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000f23 hoge`main(argc=1, argv=0x00007fff5fbff460) + 51 at hoge.c:6
   3   	int main(int argc, char **argv) {
   4   	    char *test = "This is a debug demo.";
   5   	    char *name = "edo";
-> 6   	    int age = 20;
   7
   8   	    printf("Name: %s, Age: %d\n", name, age);
   9
(lldb)
```

6行目でbreakしているのが分かります。
この状態でコマンドを受け付ける状態になるので、ここから色々なコマンドを実行してデバッグをしていきます。

#### 変数を出力する

`po`コマンド（Print Objectの略）を使って変数を出力することができます。

```console
(lldb) po name
"edo"
```

##### 構造体を出力する

`p`コマンドを使うと構造体名が出力されます。
また、`p val[0]`と、`[0]`を指定することで構造体の中身を見ることができます。
*（以下は例）*

```console
(lldb) p res
(addrinfo *) $12 = 0x00000001003004a0
(lldb) p res[0]
(addrinfo) $13 = {
  ai_flags = 0
  ai_family = 2
  ai_socktype = 1
  ai_protocol = 6
  ai_addrlen = 16
  ai_canonname = 0x0000000000000000
  ai_addr = 0x0000000100300460
  ai_next = 0x0000000000000000
}
```


### ステップ実行する

ブレークポイントで止めても、処理を進めないと先に進めません。
処理を次に進めるには`n`（next）か`c`（continue）を使って処理を進めます。


### スタックトレースを出力する

`bt`（thread backtrace）コマンドで出力することができます。

```console
(lldb) bt
* thread #1: tid = 0x53d052, 0x0000000100000f2a hoge`main(argc=1, argv=0x00007fff5fbff460) + 58 at hoge.c:8, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100000f2a hoge`main(argc=1, argv=0x00007fff5fbff460) + 58 at hoge.c:8
    frame #1: 0x00007fff8c31e5c9 libdyld.dylib`start + 1
```


### 変数の一覧を出力する

現在breakしているフレームで見ている変数の一覧を出力することができます。

```console
(lldb) frame variable
(int) argc = 1
(char **) argv = 0x00007fff5fbff460
(char *) test = 0x0000000100000f6e "This is a debug demo."
(char *) name = 0x0000000100000f84 "edo"
(int) age = 20
```

ちなみに、以下のようにすることで、該当の変数を出力することもできます。

```console
(lldb) frame variable *argv
(char *) *argv = 0x00007fff5fbff5e0 "/Path/To/hoge"

(lldb) frame variable age
(int) age = 20
```