20 Jun 2013, 10:32

gdbserverを立ちあげてリモートデバッグする方法メモ

プログラムの勉強をする開発環境は今までCygwinを利用していたが,最近はvmware上のCentOSに乗り換えた。

C言語のコードを編集するときは、Windows上でEclipseを起動してsamba経路でソースを編集してる。コンパイルを実施するときは、ssh接続でリモートシェルを起動している。

今回、gdbをEclipseから利用する方法を調べてみた。利用するのは、

gdbserver

デバッグ対象のプログラムを実行しているマシンとは異なるマシン上で GDB を実行することを可能にするプログラム。

環境

  • ターゲットPC CentOS 6.4
  • ホストPC Windows 7 (Cygwin)

gdbserverをインストールする

なにはともあれ、まずはgdbとgdbServerをターゲットPCにインストールする

yum -y install gdb
yum -y install gdb-gdbserver

Cygwinのgdbからgdbserverに接続してリモートデバッグ

CentOS上でgdbserverを立ちあげて、Windows上のCygwinで動作してているgdbからTCP接続でアクセスします。

gdbserverの起動

gdbserverの起動のための書式は以下。

gdbserer (ターゲットIP):(ポート番号) (プログラム) [引数]

例えば、hogehoge.exeをポート8081で起動する場合、

[tsu-nera]% gdbserver locallhost:8081 hogehoge.exe
Process hogehoge.exe created; pid = 3739
Listening on port 1234

これでホストPCからの接続を待っている状態になる。

ちなにみ、ポートが開いていない場合は開けておく。

sudo emacs  /etc/sysconfig/iptables
# for gdbserver
  -A INPUT -m state --state NEW -m tcp -p tcp --dport 8081 -j ACCEPT

gdbクライアントからgdbserverに接続

クライアント側でも、gdbを起動。Cygwin上のgdbを利用して、samba経路でhogehoge.exeを起動する。

gdb hogehoge.exe

リモートのターゲットに接続するためには、以下を入力。

(gdb) target remote saru:8081
Remote debugging using saru:8081
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB.  Attempting to continue with the default i386 settings.

接続完了。あとはお好きな様に。

Eclipseからgdbserverに接続してリモートデバッグ

Eclipseには、高機能なGUIインタフェースのgdbが付いている。コレを使用する。

  • プロジェクトを右クリック -> デバッグ -> デバッグの構成
  • C/C++リモート・アプリケーション -> 新規 を選択。
  • C/C++アプリケーションで、sambaから見えている実行ファイルを選択。
  • 同じビューの下のほうにある、GDB(DSF) Manual Remote Debugging ランチャーを選択。
  • デバッガータブを開き、接続タブを選択。
  • 型でTCPを選択。ホスト名とポートも入力。
  • 最後に、デバッグを押して完了。

ソースが見えないときは、ソース・ルックアップパスの設定でパス・マッピングをする。例えば、sambaでZ\ドライブに/home/tsu-neraを割り当てている場合、Z\と/home/tsu-nerを割り当てる。

これで、Eclipseから見えるはず!!!(`・ω・´)ゞ

とおもったが、breakpointをはってもgdbが止まってくれない。。。(T_T)

ステップ実行も変数の値の書き換えもできるが、ブレークポイントでトマラない。。(T_T)

5時間頑張って、今日は挫折した。このくらいで許してよ。orz

追記: gdb traceをみてみると、以下のエラー。どうやら、ソースが見えない??

789,439 26-break-insert --thread-group i1 -f /home/tsu-nera/repo/vxUnit/vxUnit/test/Testhogehoge.c:2\
4
789,510 &"No source file named /home/tsu-nera/repo/vxUnit/vxUnit/test/Testhogehoge.c.\n"
789,513 26^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="<PENDING>",pending=\
"/home/tsu-nera/repo/vxUnit/vxUnit/test/Testhogehoge.c:24",times="0",original-location="/home/tsu-ne\
ra/repo/vxUnit/vxUnit/test/Testhogehoge.c:24"}
789,513 (gdb) 

参考

26 Feb 2013, 14:12

C言語のデバッグ加速!Eclipse CDTでのgdb機能がメチャクチャ便利だ。

Eclipse CDTには、グラフィッカルなgdbインタフェースがついてきます。

これが最近便利すぎるので、オススメ機能をここらでまとめときます。

基本的な設定方法

コンパイルオプション

まずは実行ファイルを作るときにコンパイルオプションで以下を追加。

CPPFLAGS += -g -O0

-g : GDB用のデバッグ情報を実行ファイルに含める。

-Oo : コンパイラに最適化をさせない。

ルックアップパスの設定

デバッグ・パースペクティブにソースが現れないときは、ソースのパスが設定されていない。

Can’t find a source file at : hogehoge…

[ウィンドウ] > [設定] > [C/C++] > [デバッグ] > [ソース・ルックアップ・パス] から追加したいソースがあるフォルダを追加する。

GDBを実行してみる

デバッグ・パースペクティブからF11を実行できればOK。

ソースを見ながらブレークポイントをはって、ステップ実行

ソースを見ながらブレイクポイントをはれるのが嬉しい。

貼る方法も、解除する方法も、クリックひとつだ。

はった場所は、別のビューから確認できる。

2013_0226_gdb_0.png

構造体や変数のなかもスケスケ丸見え

gdbの恩恵は、変数や構造体の中身を見て、さらに値を書き換えて実行できるところだ。

構造体のネスト構造を中の中まで確認できるのがとても嬉しい。

また、xUnitではテストしづらい部分もブレークを貼って手動で値を書き換えてテストスルことができる。痒いところに手が届くとは、ここから始まった。

変数や構造体の参照は、[変数ビュー]で確認できる。

図は複雑怪奇なaddrinfo構造体とsockaddr構造体。

中身の値まで丸見えだ。なんなら、書き換えも同じビューで可能。

2013_0226_gdb_01.png

また、ソース上で変数の上にカーソルを移動するだけでも確認できる。

ステップ実行で、セグメンテーション違反した箇所まで移動できる

これについては、以前記事にまとめたので、こちらを参照。

ステップ実行のためのよく使用するショートカットも以下にまとめます。

起動 F11 gdbを起動する
再開 F8 gdbを再開する。
はじめはmainで止まるので、F8でブレイクポイントまで移動することを
ステップイン F5 ステップ実行をする。
一行ずつプログラムを進めることができる。
ステップオーバー F6 関数単位で実行する。
関数の頭でステップオーバーすると、
関数内にはいらずに次の処理へすすむ。
結構使う。
ステップ・リターン F7 現在の関数がreturnするまでを実行する。
まあまあ使う。

 

他にも、ウォッチポイントを簡単に設定できたり、逆アセンブリ結果を表示できる。

とにかく高機能だ。

こんな便利なものが、無料で使えるならば、利用しない手はないだろう。

補足

  • Eclipse 3.7 Indigoでは、gdb7.4以降のバージョンが動作しないようだ。

Undefined maintenance set command: “python print-stack off”. Try “help maintenance set”.

のようなメッセージが出るはず。そんなときは、

  • Eclipse 4.2 Junoにアップグレードする。
  • gdbをダウングレードする。

のいづれかが必要。自分はcygwinで一つ前のgdbのバージョンに設定したら動いた。

Eclipse Community Forums: CDT ≫ Error message from debugger back end

  • Eclipseを使ってない場合はInsightという方法もある。

03 Feb 2013, 01:00

GoogleTestとEclipseのGDB機能の組み合わせが最強だった件

Eclipse CDTでデフォルトで付いているグラフィカルなGDB用のインタフェースと、GoogleTestなどのxUnitをあわせて利用するとデバッグが捗ったので、メモ。

基本は動的、バグったら静的

方法は以下の通り。

  1. GoogleTestを使ってテストを書いて実行。
  2. テスト失敗したら、失敗したテストケースでブレイクポイントをはる。
  3. GoogleTestを再実行して、ブレイクしたところからステップ実行して、テスト失敗の理由を調査。

基本的には、GoogleTestで自動テストを書いていく。
しかし、テストが失敗し、その原因がよくわからないときはGDBでメモリの値の変化をステップごとに追いながらデバッグをするというスタンスだ。

EclipseのGDB機能はスゴく高性能で、
構造体のネスト構造まで、スケスケ丸見えなのだ(下品 (・∀・)ニヤニヤにや)

キーバインドでパースペクティブを行ったり来たり

キーバインド的には、

GoogleTest実行時 =>「Ctrl+ F11」
GDB起動時          => 「F11」

というようにしている。すると、実行によってEclipseのパースペクティブが[C/C++]と[デバッグ]で切り替えることができる。

設定が必要な場合は、
[ウィンドウ] > [設定] > [実行/デバッグ] > [パースペクティブ]から[C/C++ Application]を選択し、適切に設定すること。

また、ブレークポイントを設定することで、自動的に実行時にはデバッグパースペクティブに切り替えることもできる。
[ウィンドウ] > [設定] > [実行/デバッグ] から設定。(多分、これはデフェルト設定)

セグメンテーション違反対策に効果バツグン!

個人的にとてもいいなと感じたのは、セグメンテーション違反するとその直前でGoogleTestの実行処理を止めることができること。

テストコードがないコードに修正をいれるのは怖いので、まずテストを書いてから修正を入れるようにしているが、このレガシーコードへのテストを書く際に、メモリ獲得を忘れて画面が真っ赤になることがすごくたくさんあるのだ!

この潰し込みが大変で、テストを書くことを諦めることが往々にしてある。
しかし、このgdbを使った方法をとれば、驚くほど効率が上がった。

まとめ

今まで、gdbを積極的には使って来なかった。
(使い方をあまり知らなかったという方が正しいかもしれない)
手動テストなんてありえない!という偏見があったのかもしれない。

物事に偏見をもってはいけないというお話でした。

チャンチャン( ゚∀゚ )

26 Jan 2013, 00:44

[Eclipse CDT]セグメンテーション違反した箇所をGDBで特定する

Eclipse+Cygwin環境でデバッグするとき、いつもはGoogleTestを使っている。

GoogleTestを実行してセグメンテーション違反をすると、Windowsは以下のエラーを返す。

 [main] sample 10968 exception::handle: Exception: STATUS_ACCESS_VIOLATION
1714 [main] sample 10968 open_stackdumpfile: Dumping stack trace to sample.exe.stackdump

例:こんなお粗末ソース

#include

int add(int x, int y)
{
int z;
char *p;

z = x + y;
*p = 1; /* ここでセグメンテーション違反 */
return z;
}

こんなとき、Eclipseの画面からGDBを起動して、どこで落ちたかを調べると便利だったので、メモ。

環境

  • Eclipse 4.2 Juno
  • GDB 7.5
  • Cygwin 1.7.17-1

EclipseでGDBを利用するための設定

コンパイルオプション

まずは実行ファイルを作るときにコンパイルオプションで以下を追加。

CPPFLAGS += -g -O0

-g : GDB用のデバッグ情報を実行ファイルに含める。

-Oo : コンパイラに最適化をさせない。

ルックアップパスの設定

デバッグ・パースペクティブにソースが現れないときは、ソースのパスが設定されていない。

Can't find a source file at : hogehoge...

[ウィンドウ] > [設定] > [C/C++] > [デバッグ] > [ソース・ルックアップ・パス] から追加したいソースがあるフォルダを追加する。

GDBを実行してみる

デバッグ・パースペクティブからF11を実行できればOK。

Defaultではmainでbreakするように設定されているので、[再開]F8する。

すると、STATUS_ACCESS_VIOLATIONが発生した場所まで移動して、

ソースを表示してくれる。

image

まとめ

今回、xUnitとGDBを組み合わせることでデバッグがさらに効率的になるのではと思い、記事にしてみた。

この方法の前は、いちいちテストやソースにprintやexitを仕込んでいたが、始めっからgdbを使えばよかったなと、今頃ながら気づいたのだった。

xUnitでテストするようになってから、さすがにもう手動でのテストをする気にはなれないが、こんな組み合わせもいいかもしれない。

Eclipse+Cygwin環境でデバッグするとき、いつもはGoogleTestを使っている。

GoogleTestを実行してセグメンテーション違反をすると、Windowsは以下のエラーを返す。

ツꀀツꀀツꀀツꀀツꀀ 1 [main] sample 10968 exception::handle: Exception: STATUS_ACCESS_VIOLATION
1714 [main] sample 10968 open_stackdumpfile: Dumping stack trace to sample.exe.stackdump

例:こんなお粗末ソース

#include

int add(int x, int y)

{

int z;

char *p;

z = x + y;

*p = 1;ツꀀツꀀツꀀ /* ここでセグメンテーション違反 */

return z;

}

こんなとき、Eclipseの画面からGDBを起動して、どこで落ちたかを調べると便利だったので、メモ。

環境

  • Eclipseツꀀ 4.2 Juno
  • GDB 7.5
  • Cygwin 1.7.17-1

EclipseでGDBを利用するための設定

コンパイルオプション

まずは実行ファイルを作るときにコンパイルオプションで以下を追加。

CPPFLAGS += -g -O0

-g : GDB用のデバッグ情報を実行ファイルに含める。

-Oo : コンパイラに最適化をさせない。

ルックアップパスの設定

デバッグ・パースペクティブにソースが現れないときは、ソースのパスが設定されていない。

Can’t find a source file at : hogehoge…

[ウィンドウ] > [設定] > [C/C++] > [デバッグ] > [ソース・ルックアップ・パス] から追加したいソースがあるフォルダを追加する。

GDBを実行してみる

デバッグ・パースペクティブからF11を実行できればOK。

Defaultではmainでbreakするように設定されているので、[再開]F8する。

すると、STATUS_ACCESS_VIOLATIONが発生した場所まで移動して、

ソースを表示してくれる。

image

まとめ

今回、xUnitとGDBを組み合わせることでデバッグがさらに効率的になるのではと思い、記事にしてみた。

この方法の前は、いちいちテストやソースにprintやexitを仕込んでいたが、始めっからgdbを使えばよかったなと、今頃ながら気づいたのだった。

xUnitでテストするようになってから、さすがにもう手動でのテストをする気にはなれないが、こんな組み合わせもいいかもしれない。