組み込みLinuxでリモートデバッグするときのgdbのセットアップ方法

ふだんはあまり使わないのだけど、忘れた頃に必要になるのでここに書いておく。

#前提

## デバッグ対象
ARM Linuxのユーザープロセスが今回のデバッグ対象。
gcc で書かれている。(今回は gcc 4.9)
ARM LinuxのIPアドレスは 192.168.129.32
gdbで使用するポート番号は 1234

## デバッグホスト
x86_64 のPC Linux
デバッグ対象のARM Linuxとは同一ネットワーク内にある。
デバッグ対象のビルドはここで行っている。ここにソースコードがある。
ソースコードをgistに貼った。[loop.c](https://gist.github.com/tetsu-koba/7b6a8c5c009edb5cbcf0641397864082#file-loop-c)
ビルドに使用するツールチェイン、gdbはbuildrootで作った。

#デバッグ用のgccのコンパイルオプション
デバッグ対象のプログラムをコンパイルするときに、gccに -g オプションをつける。(必須)
最適化オプションは -Og に変更する。(推奨)
-Og は最適化をデバッグ情報の妨げにならない範囲で行う。
gccでは最適化オプションが複数ついていた場合には最後のものが有効になる。よってMakefileの中に以下を追加するとよい。

```
CFLAGS += -g -Og
```

```
$ make
arm-buildroot-linux-gnueabi-gcc  -g -Og -c -o loop.o loop.c
arm-buildroot-linux-gnueabi-gcc  -o loop loop.o
```

#gdbの設定ファイル
デバッグホストの中でデバッグ対象のソースコードがあるディレクトリでgdbを起動することになるが、そのディレクトリに以下の内容を .gdbinit のファイル名で書いておく。

``` :.gdbinit
set sysroot ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/

target remote 192.168.129.32:1234
```

sysroot の設定が重要。デバッグ情報付きのlibc.soなどの共有ライブラリのある場所を指定する。これが無いとバックトレースの表示が正しくできない。
$sysrot/lib/の下にlibc.soがあることを確認する。

```
$ ls -l ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc.so*
lrwxrwxrwx 1 koba koba 12 Dec 12 19:09 ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc.so.6 -> libc-2.23.so
$ file ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc-2.23.so 
../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc-2.23.so: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.4.0, not stripped
```

#デバッグ対象のARM Linuxでgdbserver を起動する

今回はすでに実行中のプロセスにアタッチする。プロセスIDは361
gdbとの通信に使用するポートは1234
必ずroot権限で実行すること。

```
ARM# gdbserver --attach :1234 361
Attached; pid = 361
Listening on port 1234
```

#デバッグホストでgdbを起動する
デバッグ対象のオブジェクトファイルをloop とする。

```
$ file loop
loop: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.4.0, not stripped
```

ARM用にビルドされたgdbを起動する。

```
t$ arm-buildroot-linux-gnueabi-gdb loop
GNU gdb (GDB) 7.10.1
Copyright (C) 2015 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 "--host=x86_64-unknown-linux-gnu --target=arm-buildroot-linux-gnueabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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 loop...done.
0xb6e3abac in nanosleep ()
   from ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc.so.6
(gdb) 
```

#バックトレースを表示してみる

```
(gdb) bt
#0  0xb6e3abac in nanosleep ()
   from ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc.so.6
#1  0xb6e3aaa4 in sleep ()
   from ../buildroot/buildroot-2016.05/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/lib/libc.so.6
#2  0x0001042c in func2 () at loop.c:16
#3  0x0001045c in func1 () at loop.c:7
#4  0x00010468 in main () at loop.c:23
(gdb) 
```

#ブレークポイントをかけたり、変数を見たりしてみる

```
(gdb) b func1
Breakpoint 1 at 0x10458: file loop.c, line 7.
(gdb) c
Continuing.

Breakpoint 1, func1 () at loop.c:7
7			func2();
(gdb) p cnt
$1 = 82
(gdb) 
```

#参考
gdbのドキュメント
http://sourceware.org/gdb/download/onlinedocs/gdb/index.html