Post on 24-May-2015
description
Debug Hacks 8/13/'10
よしおかひろたか (Debug Hacks著者 )hyoshiok@gmail.com
http://d.hatena.ne.jp/hyoshiok/http://blog.miraclelinux.com/yume/
Debug Hacks
● Debug Hacks --デバッグを極めるテクニック &ツール
● 吉岡 弘隆 , 大和 一洋 ,大 岩 尚宏 , 安部 東洋 , 吉田
俊輔
● ISBN:978-4-87311-404-0
● オライリー・ジャパン
● 2009年 4月 22日
デバッグ入門
● デバッグとは、ソフトウェアの不具合(バグ)を修正するプロセス
● ソフトウェアの不具合を発見するプロセスのことはテストとよぶ
● ソフトウェアの不具合を修正するのではなく回避する方法をトラブルシューティングとよぶ
● Debug Hacksは主に(狭義の)デバッグについて解説した書籍
トラブルシューティング
バグ
● ソフトウェアの不具合(仕様との差異)
– テストで発見する
– それ以外で発見される● …たまたま使っていて発見、
バグのパターン
● 正常に終了(バグではない)
● 期待する動作をしないで終了
– 期待する出力をしない、クラッシュ、遅い、
● 終了しない
– デッドロック、無限ループ、
デバッグのプロセス
● 問題の再現
– 環境設定
– ヒアリング
● 現象の確認
● 問題の理解、解析
● 原因が不明?
– 過去にあった同様の問題を検索(バグ DBなど)– バグ発生へ、そなえる
– 同僚に説明する
– コミュニティへ質問する
デバッグのプロセス
● バグ修正
● 動作確認
– バグが直っていることの確認
– デグレード/エンバグがないことの確認(リグレッションテストの実行)
● ピアレビュー
● テストプログラムの作成
● コミュニティへの報告(必要であれば)
デバッガを使おう
● 任意の場所にブレークポイントを設定できる。
● プログラムを変更しなくても、変数の値を確認することができる。
● プログラムを変更しなくても、変数に任意の値を設定できる。
● 変数に値が代入されたときに停止することができる。
● コールグラフ(バックトレース)を表示できる。
● printf()デバッグださいよね。
デバッグのプロセス
● 期待しない値を出力して終了というケース
– 任意の場所にブレークポイントを設定
– 実行
– 任意の変数の値を確認(期待通りか)● 期待通りじゃない場合は、実行前半部分にバグ?● 期待通りの場合は、実行後半にバグ?
● 終了しないケースは後述
GDBの基礎の基礎
● Gccでコンパイルする $gcc -g -Wall-Wallはとっても重要その他、下記のフラグも-W -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wfloat-equal -Wpointer-arith
● Makefile では CFLAGSにオプションを追加● INSTALLや READMEファイルなどを確認
GDBの基礎の基礎
● 起動
● $gdb 実行ファイル名● $gdb -c コアファイル 実行ファイル名● emacsから起動するときは、M-x gdb
GDBの基礎の基礎
● ブレークポイントの設定
– 任意の場所で停止する
● break 関数名● break 行番号● break ファイル名:行番号● break ファイル名:関数名● break [+|-]オフセット● break *アドレス
ブレークポイント
● 設定したブレークポイントの確認info break
実行
● run コマンド● run 引数● main()にブレークポイントを設定してmain()まで実行する
– startコマンド
ブレークしたら
● どこで停止したか。backtraceコマンド (btと略す )
変数の表示
● print[/フォーマット ] 変数– `x' 16進数で表示– `d' 10進数で表示– `u' 符号なしの 10進数で表示– `o' 8進数で表示– `t' 2進数で表示。 `t' は "two" からくる。– `a' アドレス– `c' 文字 (ASCII)として表示– `f' 浮動小数点– `s' 文字列として表示
アドレスの表示
● x[/NFU] アドレス● N繰り返し回数● Fフォーマット● U単位
– `b' バイト– `h' ハーフバイト( 2バイト)– `w' ワード( 4 バイト) デフォルト
– `g' ジャイアントバイト (8バイト)
逆アセンブル
● disassemble コマンド
実行の再開
● ステップ実行
● continue● finish/until
ステップ実行
● ソースコード一行分実行する
● next– ソースコード一行分実行し停止する。関数呼び出しの場合、関数を実行後停止する。
● step– ソースコード一行分実行し停止する。関数呼び出しの場合、その関数の最初の実行文を実行し停止する。(もぐって行く)
continue
● 実行を再開する
– ブレークポイントで停止する
– 実行を終了する
finish/until
● finish 関数を最後まで実行– 関数の入り口でいろいろ調べた後、最後まで一気に実行したいとき便利
● until ループが終わるまで実行– ループの入り口でいろいろ調べた後、ループを一気に実行したいとき便利
実行の再開のまとめ
● next/step● continue● finish/until
変数へ代入されたとき止めたい
● ウォッチポイント。任意の変数に代入された時に停止する。
● watch 式(式が変更された時に停止)● awatch 式(式が参照、変更された時に停止)● rwatch 式(式が参照された時に停止)● どこであるアドレスが変更されるか、よく分からないときなどに利用すると便利。実行速度の低下がある。
その他のブレークポイント
● ハードウェアブレークポイント (hbreak)● 一時ブレークポイント (tbreak)
変数の値の変更
● set variable 変数=式● ソースコードを変更する前に試行錯誤して確認できる。
その他のコマンド
● info threads● thread● info registers● frame
期待しない値のケースのまとめ
● 任意の場所にブレークポイントを設定
● 実行開始
● 停止したら値の確認
● 実行の再開
● バグの原因を見つけるまで上記を繰り返す
終了しない場合
● 無限ループ、デッドロックなどで終了しない場合のデバッグ
● 当該プロセスのプロセス IDを調べる$ ps aux|grep プログラム名
● プロセスへアタッチする
● attach プロセス ID● アタッチすると実行を停止するので、デバッグをはじめる
コアファイルがある場合
● $gdb -c コアファイル プログラム名
● コアファイルを生成した時点でのスタックトレースなどが見れる
まとめ
● GDBの基本の基本を紹介した● GDBは便利な機能満載なので使ってみよう● Debug Hacksの感想、コメント、誤植の発見などなど、著者 (hyoshiok@gmail.com)まで教えてください。
付録: Debug Tools
● kprobes● jprobes● KAHO● systemtap● VMware Vprobe● crash● gdb
kprobes
● 任意のアドレスにプローブを挿入
● Debug Hacks, #47, #49, #50
jprobes
● 関数の先頭にプローブを設定することに特化しているので、 kprobesよりもお手軽
● Debug Hacks, #48
KAHO
● プロセスの関数を置き換えることができる
● Debug Hacks, #51
systemtap
● kprobesを利用して、独自のスクリプト言語を用いてプローブハンドラを作成する。
● Debug Hacks, #52, #53
VMware Vprobe
● ゲストOSの状態を調査することができる● Debug Hacks, #61
crash
● kernel crash dump utility● Debug Hacks, #21
gdb
● デバッガー
● Debug Hacks, #5, #6, #7
参考文献
● Intel® 64 and IA-32 Architectures Software Developer's Manualshttp://www.intel.com/products/processor/manuals/index.htm