GDB利用法 第2回

前回の(GDB利用法第1回)の続きです。

 

 

3. 自動で実行する

・全体の動作をファイルに記述し、gdbの起動時に-xで指定します。
・細かな設定は別ファイルに記述し、gdbの中で source コマンドで指定します。
・set pagination off を設定しないと途中で実行を続けるか問い合わされます。
これにより複雑な自動デバッグが容易になります。
またデバッグツール以外にテストツールとしても利用することが可能です。

以下に2.4の例を記述します

3.1. GDBから実行
$gcc -shared -o testlib.so testlib.c
$gcc sample.c testlib.so
$export LD_LIBRARY_PATH=(testlib.soのパス)
$gdb -x baseFile.txt ./a.out

自動で実行が続く

^C (Ctrl-C) で中断
(gdb) q   (c なら再開)
The program is running. Quit anyway (and detach it)? (y or n) y
$

○sample.c の内容
#include <stdio.h>

int CheckNum;

function1(int *no)
{
printf(“no=%d\n”,*no);
(*no)++;
}

main()
{
CheckNum = 0;
while(1){
function1(&CheckNum);
sleep(1);
if(CheckNum>10) CheckNum = 0;
}
}

○testlib.c の内容
void resetCheckNum(int *no)
{
*no = 0;
}

○baseFile.txt の内容
set pagination off
set logging file baseFile.log
watch CheckNum
source watch1.txt
set logging on
run

○watch1.txt の内容
command 1
where
if CheckNum==3
call resetCheckNum(&CheckNum)
end
echo CheckNum\n
p CheckNum
c
end

3.2. 実行中にアタッチして実行

以下の手順だと既に実行中のプログラムにアタッチし確認したのちに
プログラムは終了せずにgdbだけ終了させることができます。

$export LD_LIBRARY_PATH=(testlib.soのパス)
$./a.out & (先に実行しておく 別ウインドウが望ましい)
$ps -a でa.outのPIDをチェック
$gdb -p a.outのPID
(gdb)source attachFile.txt

自動で実行が続く

^C (Ctrl-C) で中断
(gdb) q   (c なら再開)
The program is running. Quit anyway (and detach it)? (y or n) y
$(a.outは終了しない)

○attachFile.txt の内容 (baseFile.txtとの差は基本的には最後のrunがcに)
set pagination off
set logging file attachFile.log
watch CheckNum
source watch1.txt
set logging on
c

3.3. 外部と連携する

gdbからsystem()を使って外部のプログラムを起動することができます。
特定の条件になったらログを出力したり、プログラムの起動を行えます。
プログラムの状態を監視したり、他のプログラムを制御することができます。
またスナップショットを取ることで試験の証跡の自動取得も可能になります。

 

4. リモートデバッグを行う

完全なリモートではありませんが、プログラムを実行中のマシンでgdbのリモートI/Fである
gdbserverを起動することで別のPCからgdbで操作が可能になります。
ただし操作側にもプログラム、-gでコンパイルしている場合はソースが必要です。

4.1. リモート側の設定

1) 新規に起動する場合
$gdbserver 操作PC名(IPアドレス):使用ポート番号(任意) プログラム名(+引数)

2) 既に起動されている場合
$gdbserver 操作PC名(IPアドレス):使用ポート番号(任意) –attach PID

これでサーバの接続待ちになります。
1)の場合は起動されて接続待ちのイメージです。(先頭で停止)
2)の場合は動作が停止した状態になりますので注意してください。

4.2. 操作側の設定

操作側は新規の起動でも動作中に接続している場合でも同じ操作になります
$gdb プログラム名
(gdb)target remote 操作対象PC(IPアドレス):使用ポート番号(操作対象で設定したポート)
これで操作対象と接続されます。以降は基本的に操作は変わりません。
ただ、操作先はすでに起動状態なのでrunは使用せずcまたはn(s)で実行を開始します。

4.3. 終了

新規起動の場合はqで終了することで操作先のgdbserver、プログラム共に終了します。
起動中だった場合もqで終了すると同上になってしまいます。
プログラムを終了させない場合は detachでgdbserverのみ終了させることができます。
(プログラムはそのまま動作を続けます)

 

付録

直接gdbとは関係ないが有効なコマンドをおげておきます。

1) 登録されているシンボルの表示
$nm オブジェクトファイル
ファイル内のシンボルが表示されます。ブレークポイントの確認や設定に利用できます。
基本16進で表示されますのでブレークポイントの設定に利用するときは0xをつけて16進で
指示してください。

2) ソースコードのdefine等の展開(実際の値を知る)
$gcc -E -I(必要なインクルードパス) ソースコード
ソースコード内のdefine等が展開され、標準出力に出力されます。
defineで定義された名称ではなく実際の値を確認することができます。(エラーコード等)
-C を併用するとソース内のコメントも表示されます。
なお展開ファイル(include)の名前やソース上での行数は先頭に#をつけた行で埋め込まれ
ますので元ソースとの突合せは容易です。
(注)インクルードの指定が漏れる(誤る)と有効になる行(ifdef)が異なることがあります。

3) カバレジを取る
$gcov ソースファイル.gcda
gccコンパイル時に-coverageオプションを付けたモジュールを実行すると「XXXXX.gcda」
が生成されます。gcovで「XXXXX.gcov」にカバレジ状況が格納されます。
これはgdbで実行した場合も有効なのでgdbと合わせたカバレジテストが可能になります。
「xxxxx.gcda」を残しておけばカバレジ情報は追加されます。(消すと新規)

以上

 

次回はテスト駆動について簡単に触れたいと思います。

Pocket