(57)【特許請求の範囲】
【請求項１】
プログラムの動作の差異を発見するためのプログラム動作比較装置であって、
プログラムを実行するプログラム実行手段と、
プログラム自身が関数の実行履歴を出力可能なように該プログラムの実行ファイルを変更し、前記プログラム実行手段により、実行した該プログラムの実行履歴を取得して実行履歴記憶手段に格納するプログラム実行履歴収集手段と、
前記実行履歴記憶手段のプログラムの実行履歴を、実行された該プログラムの関数コールスタックの深さと、出現パターンに基づいて関数コールシーケンスの局所を関数ブロックとして区切り、関数ブロック記憶手段に格納するプログラム実行履歴分割手段と、
前記関数ブロック記憶手段の前記関数ブロックと、前記プログラム実行手段により実行中のプログラムの関数コールシーケンスを比較し、異なる箇所を検出し、比較結果記憶手段に格納する比較手段と、
を有することを特徴とするプログラム動作比較装置。
【請求項２】
前記プログラム実行履歴収集手段は、
プログラムの実行履歴として取得する関数について、該関数についての情報を収集するためのプログラムの実行ファイルを変更する実行ファイル変更手段と、
取得する関数について詳細な情報を取得するために必要となる値を取得するデバッグ情報取得手段と、
プログラムの実行ファイル内で定義されている関数や、ユーザが指定した共有ライブラリの関数について、該プログラムが前記プログラム実行手段により実行された時刻、関数名、引数、コールスタックの深さの値、返り値を含む情報を取得し、取得した情報を実行履歴記憶手段に登録する実行履歴収集手段と、
を有する請求項１記載のプログラム動作比較装置。
【請求項３】
前記プログラム実行履歴分割手段は、
前記実行履歴記憶手段に格納されている履歴情報を読み込んで、関数の呼び出しのみに着目し、呼び出した関数のコールスタックの深さの値が小さくなったところで区切り、区切られた箇所を１つの関数ブロックとする実行履歴区分手段と、
前記関数ブロック内の関数がその実行順序も含め同一となる関数ブロックが存在するかを検索し、存在する場合は、その次の関数ブロックについても関数ブロック内の関数がその実行順序も含め、同一であるかを調べる処理を繰り返し、同一である関数ブロックが存在した場合には、その一連の長さが最も長い関数ブロックに対して、複数の関数ブロックを１つの関数ブロックとしてまとめ、前記関数ブロック記憶手段に登録する手段と、
前記関数ブロック内の関数の引数、返り値が、全ての関数において同一か、同一の値を持つ関数が存在するか、全ての関数において異なっているかを関数と関連付けした前記関数ブロック記憶手段に登録する手段と、
を有する請求項１記載のプログラム動作比較装置。
【請求項４】
前記比較手段は、
前記関数ブロック記憶手段から前記関数ブロックを読み出して、該関数ブロックと前記プログラム実行手段により実行中のプログラムの関数コールシーケンスを比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出する手段と、
前記関数コールシーケンスのみの比較では異なる箇所が検出できなかった場合に、関数ブロック内の実行された関数についての情報と、前記実行中のプログラムが実行した関数についての情報を比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出する手段と、
を有する請求項１記載のプログラム動作比較装置。
【請求項５】
プログラムの動作の差異を発見するためのプログラム動作比較方法であって、
プログラム自身が関数の実行履歴を出力可能なように該プログラムの実行ファイルを変更し、該プログラムを実行する機能により、実行した該プログラムの実行履歴を取得して実行履歴記憶手段に格納するプログラム実行履歴収集ステップと、
前記実行履歴記憶手段のプログラムの実行履歴を、実行された該プログラムの関数コールスタックの深さと、出現パターンに基づいて関数コールシーケンスの局所を関数ブロックとして区切り、関数ブロック記憶手段に格納するプログラム実行履歴分割ステップと、
前記関数ブロック記憶手段の前記関数ブロックと、前記プログラムを実行する機能により実行中のプログラムの関数コールシーケンスを比較し、異なる箇所を検出し、比較結果記憶手段に格納する比較ステップと、
を行うことを特徴とするプログラム動作比較方法。
【請求項６】
前記プログラム実行履歴収集ステップにおいて、
プログラムの実行履歴として取得する関数について、該関数を取得するためのプログラムの実行ファイルを変更する実行ファイル変更ステップと、
呼ばれた関数から呼び出し元に戻るときの時刻、呼ばれた関数内で変更された引数、返り値を取得するデバッグ情報取得ステップと、
プログラムの実行ファイル内で定義されている関数や、ユーザが指定した共有ライブラリの関数について、該プログラムが前記プログラムを実行する機能により実行された時刻、関数名、引数、コールスタックの深さの値、返り値を含む情報を取得し、取得した情報を実行履歴記憶手段に登録する実行履歴収集ステップと、
を行う請求項５記載のプログラム動作比較方法。
【請求項７】
プログラム実行履歴分割ステップにおいて、
前記実行履歴記憶手段に格納されている履歴情報を読み込んで、関数の呼び出しのみに着目し、呼び出した関数のコールスタックの深さの値が小さくなったところで区切り、区切られた箇所を１つの関数ブロックとする実行履歴区分ステップと、
前記関数ブロック内の関数がその実行順序も含め同一となる関数ブロックが存在するかを検索し、存在する場合は、その次の関数ブロックについても関数ブロック内の関数がその実行順序も含め、同一であるかを調べる処理を繰り返し、同一である関数ブロックが存在した場合には、その一連の長さが最も長い関数ブロックに対して、複数の関数ブロックを１つの関数ブロックとしてまとめ、前記関数ブロック記憶手段に登録するステップと、
前記関数ブロック内の関数の引数、返り値が、全ての関数において同一か、同一の値を持つ関数が存在するか、全ての関数において異なっているかを関数と関連付けした前記関数ブロック記憶手段に登録するステップと、
を行う請求項５記載のプログラム動作比較方法。
【請求項８】
前記比較ステップにおいて、
前記関数ブロック記憶手段から前記関数ブロックを読み出して、該関数ブロックと前記プログラムを実行する機能により実行中のプログラムの関数コールシーケンスを比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出するステップと、
前記関数コールシーケンスのみの比較では異なる箇所が検出できなかった場合に、関数ブロック内の実行された関数の引数や返り値と、前記実行中のプログラムが実行した関数の引数や返り値を比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出するステップと、
を行う請求項５記載のプログラム動作比較方法。
【請求項９】
請求項１乃至４のいずれか１項に記載のプログラム動作比較装置を構成する各手段としてコンピュータを機能させるためのプログラム動作比較プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、プログラム動作比較装置及び方法及びプログラムに係り、プログラムを実行する環境や、動作するプログラムのバージョンなどのプログラムやその動作環境の違いによって発生するプログラム動作の差異を検出することにより、エラーが発生してからその原因を特定するまでの時間を短縮するためのプログラム動作比較装置及び方法及びプログラムに関する。
【背景技術】
【０００２】
現在のデバッグ技術として、プローブをプログラムに挿入する方法、プロファイラやシステムモニタ、デバッガ、ダンプ、トレーサやロガーが存在する。
【０００３】
プローブをプログラムに挿入することによって、デバッグする場合、プログラムのどこにプローブを挿入するかが問題となる。このとき、エラーが発生してからバグを発見するまでの時間の長さは、プログラム自身と、プローブを挿入したユーザのスキルに依存する。そのため、プローブをプログラムに挿入する方法は、エラーの発生からバグを特定するまでの時間を短くする方法ではない。
【０００４】
プロファイラやシステムモニタは、プログラムの計算機資源量の消費量を監視するための方法であるため、プログラムの実行速度の低下といったプログラムの計算機資源消費量に関わるバグを発見する場合には有用だが、プログラムの実行速度、プログラムの処理手順に依存して顕在化するバグ、例えば、競合問題に関するバグを発見することはできない。
【０００５】
デバッガは、ブレークポイントの挿入位置に、エラーが発生してからバグを特定するまでの時間に依存する。具体的には、よりプログラミングスキルのあるユーザがブレークポイントを挿入した方が、エラーが発生してからバグを発見するまでの時間が短くなる傾向にある。
【０００６】
また、自動的にブレークポイントを挿入し、ユーザのスキルに依存せず、エラーが発生してからバグを発見するまでの時間を短くする方法もある（例えば、特許文献１参照）しかし、実行中のプログラムの情報を取得する手段として、ブレークポイントを使用する場合、コンテキストスイッチといったオーバヘッドが高い処理が発生するため、プログラムの実行速度が大幅に低下する。
【０００７】
ダンプを用いてデバッグする場合、プログラムの情報を取得するタイミングが問題となる。ダンプでは、プログラムが実行不可能となるエラーが発生した時や、特定の外部イベントが発生した時にプログラムの情報を取得する。これらのタイミングにおいて取得したプログラムの情報から、プログラムの実行速度、プログラムの処理手順に依存して顕在化するバグを発見することは困難である。
【０００８】
トレーサやロガーは、実行された関数やシステムコールの実行時刻、関数名、引数、返り値などを自動的に取得する。このため、ポータビリティ性が十分に考慮され、モジュール化が進んだプログラムでは、プログラムの処理手順に依存するバグを発見するのに十分な情報が取得できると考えられ、エラーが発生してからバグを発見するまでの時間を短くすることができるため、実行履歴を取得するために必要となる処理時間を低減することができる。しかし、従来のトレーサやロガーは、実行された関数の引数や返り値を正確に取得していない。
【特許文献１】特開平７−７３０７０号公報
【発明の開示】
【発明が解決しようとする課題】
【０００９】
上記のように、従来のデバッグ手法には、エラーが発生してからバグを発見するまでの時間がデバッグを行うユーザのプログラミングスキルに依存している。さらに、デバッグ手法によっては、プログラムの実行速度、プログラムの処理手順に依存して顕在化するバグを発見することができない。
【００１０】
本発明は、上記の点に鑑みなされたもので、デバッグを行うユーザのプログラミングスキルに依存せず、プログラムの実行速度、プログラムの処理手順に依存して顕在化するバグを発見し、バグを特定するために必要となる情報を自動的に収集するためのプログラム動作比較装置及び方法及びプログラムを提供することを目的とする。
【課題を解決するための手段】
【００１１】
図１は、本発明の原理構成図である。
【００１２】
本発明（請求項１）は、プログラムの動作の差異を発見するためのプログラム動作比較装置であって、
プログラムを実行するプログラム実行手段４０と、
プログラム自身が関数の実行履歴を出力可能なように該プログラムの実行ファイルを変更し、プログラム実行手段４０により、実行した該プログラムの実行履歴を取得して実行履歴記憶手段１８０に格納するプログラム実行履歴収集手段１００と、
実行履歴記憶手段１８０のプログラムの実行履歴を、実行された該プログラムの関数コールスタックの深さと、出現パターンに基づいて関数コールシーケンスの局所を関数ブロックとして区切り、関数ブロック記憶手段２５０に格納するプログラム実行履歴分割手段２００と、
関数ブロック記憶手段２５０の関数ブロックと、プログラム実行手段４０により実行中のプログラムの関数コールシーケンスを比較し、異なる箇所を検出し、比較結果記憶手段３７０に格納する比較手段３００と、を有する。
【００１３】
また、本発明（請求項２）は、プログラム実行履歴収集手段１００において、
プログラムの実行履歴として取得する関数について、該関数についての情報を収集するためのプログラムの実行ファイルを変更する実行ファイル変更手段と、
取得する関数について、詳細な情報を取得するために必要となる値を取得するデバッグ情報取得手段と、
プログラムの実行ファイル内で定義されている関数や、ユーザが指定した共有ライブラリの関数について、該プログラムがプログラム実行手段により実行された時刻、関数名、引数、コールスタックの深さの情報を取得し、取得した情報を実行履歴記憶手段１８０に登録する実行履歴収集手段と、を有する。
【００１４】
また、本発明（請求項３）は、プログラム実行履歴分割手段２００において、
実行履歴記憶手段１８０に格納されている履歴情報を読み込んで、関数の呼び出しのみに着目し、呼び出した関数のコールスタックの深さの値が小さくなったところで区切り、区切られた箇所を１つの関数ブロックとする実行履歴区分手段と、
関数ブロック内の関数がその実行順序も含め同一となる関数ブロックが存在するかを検索し、存在する場合は、その次の関数ブロックについても関数ブロック内の関数がその実行順序も含め、同一であるかを調べる処理を繰り返し、同一である関数ブロックが存在した場合には、その一連の長さが最も長い関数ブロックに対して、複数の関数ブロックを１つの関数ブロックとしてまとめ、関数ブロック記憶手段２５０に登録する手段と、
関数ブロック内の関数の引数、返り値が、全ての関数において同一か、同一の値を持つ関数が存在するか、全ての関数において異なっているかを関数と関連付けした関数ブロック記憶手段２５０に登録する手段と、を有する。
【００１５】
また、本発明（請求項４）は、比較手段３００において、
関数ブロック記憶手段２５０から関数ブロックを読み出して、該関数ブロックとプログラム実行手段により実行中のプログラムの関数コールシーケンスを比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出する手段と、
関数コールシーケンスのみの比較では異なる箇所が検出できなかった場合に、関数ブロック内の実行された関数の引数や返り値と、実行中のプログラムが実行した関数の引数や返り値を比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出する手段と、を有する。
【００１６】
図２は、本発明の原理を説明するための図である。
【００１７】
本発明（請求項５）は、プログラムの動作の差異を発見するためのプログラム動作比較方法であって、
プログラム自身が関数の実行履歴を出力可能なように該プログラムの実行ファイルを変更し、該プログラムを実行する機能（プログラム実行手段）により、実行した該プログラムの実行履歴を取得して実行履歴記憶手段に格納するプログラム実行履歴収集ステップ（ステップ１）と、
実行履歴記憶手段のプログラムの実行履歴を、実行された該プログラムの関数コールスタックの深さと、出現パターンに基づいて関数コールシーケンスの局所を関数ブロックとして区切り、関数ブロック記憶手段に格納するプログラム実行履歴分割ステップ（ステップ２）と、
関数ブロック記憶手段の関数ブロックと、プログラムを実行する機能により実行中のプログラムの関数コールシーケンスを比較し、異なる箇所を検出し、比較結果記憶手段に格納する比較ステップ（ステップ３）と、を行う。
【００１８】
また、本発明（請求項６）は、プログラム実行履歴収集ステップ（ステップ１）において、
プログラムの実行履歴として取得する関数について、該関数についての情報を収集するためのプログラムの実行ファイルを変更する実行ファイル変更ステップと、
呼ばれた関数から呼び出し元に戻るときの時刻、呼ばれた関数内で変更された引数、返り値を取得するデバッグ情報取得ステップと、
プログラムの実行ファイル内で定義されている関数や、ユーザが指定した共有ライブラリの関数について、該プログラムがプログラムを実行する機能により実行された時刻、関数名、引数、コールスタックの深さの値、返り値を含む情報を取得し、取得した情報を実行履歴記憶手段に登録する実行履歴収集ステップと、を行う。
【００１９】
また、本発明（請求項７）は、プログラム実行履歴分割ステップ（ステップ２）において、
実行履歴記憶手段に格納されている履歴情報を読み込んで、関数の呼び出しのみに着目し、呼び出した関数のコールスタックの深さの値が小さくなったところで区切り、区切られた箇所を１つの関数ブロックとする実行履歴区分ステップと、
関数ブロック内の関数がその実行順序も含め同一となる関数ブロックが存在するかを検索し、存在する場合は、その次の関数ブロックについても関数ブロック内の関数がその実行順序も含め、同一であるかを調べる処理を繰り返し、同一である関数ブロックが存在した場合には、その一連の長さが最も長い関数ブロックに対して、複数の関数ブロックを１つの関数ブロックとしてまとめ、関数ブロック記憶手段に登録するステップと、
関数ブロック内の関数の引数、返り値が、全ての関数において同一か、同一の値を持つ関数が存在するか、全ての関数において異なっているかを関数と関連付けした関数ブロック記憶手段に登録するステップと、を行う。
【００２０】
また、本発明（請求項８）は、比較ステップ（ステップ３）において、
関数ブロック記憶手段から関数ブロックを読み出して、該関数ブロックとプログラムを実行する機能により実行中のプログラムの関数コールシーケンスを比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出するステップと、
関数コールシーケンスのみの比較では異なる箇所が検出できなかった場合に、関数ブロック内の実行された関数の引数や返り値と、実行中のプログラムが実行した関数の引数や返り値を比較することにより、該実行中のプログラムの動作がユーザの想定した動作と異なる箇所を検出するステップと、を行う。
【００２１】
本発明（請求項９）は、請求項１乃至４のいずれか１項に記載のプログラム動作比較装置を構成する各手段としてコンピュータを機能させるためのプログラム動作比較プログラムである。
【発明の効果】
【００２２】
本発明によれば、プログラムが実行中にエラーが発生した場合に、このプログラムの実行情報を自動的に収集することにより、ユーザが能動的にプログラムの動作情報を収集する必要がなくなるため、エラーが発生してからバグを発見するまでの時間を短くすることができる。
【発明を実施するための最良の形態】
【００２３】
以下、図面と共に本発明の実施の形態を説明する。
【００２４】
本発明は、プログラム実行履歴収集装置、プログラム実行履歴分割装置、プログラム実行履歴比較装置の各処理を行うことにより、エラーを発見してからそのバグを発見するまでの時間を短くすることを可能とする。具体的には、テストで使用する入力値といった、ユーザが出力結果まで想定できる入力値によって実行した実行履歴を取得し、その実行履歴とエラーが発生した実行履歴を比較することによって、エラーが発生してからバグを発見するまでの時間を短くすることができる。
【００２５】
以下、「関数コールシーケンス」とは、プログラムが実行した関数についての実行履歴であり、プログラムが実行されてから終了するまでの間に、実行された関数の順番である。
【００２６】
「特異性の高い関数」とは、同一プログラムによって作成された関数コールシーケンス内に呼び出し関係が同一となる関数が存在しない、または、最も実行率が低い関数のことである。特異性の高い関数ブロックについても、特異性の高い関数と同意である。
【００２７】
［プログラム実行履歴収集装置］
図３は、本発明の一実施の形態におけるプログラム実行履歴収集装置の構成を示す。
【００２８】
プログラム実行履歴収集装置１００は、プログラム自身が自身のメモリ上のデータを出力するようにメモリにロードされた実行ファイル１０を変更する。変更するタイミングは、メモリにロードされた直後（プログラムのmain関数が実行される前）、または、プログラムが実行中の場合は、ＯＳの機能を使用してプログラムを停止させた時である。また、出力するデータは、実行された時刻、関数名、引数、返り値である。
【００２９】
同図に示すプログラム実行履歴収集装置（ロガー装置）１００は、実行ファイル変更部１１０、デバッグ情報取得部１２０、実行履歴収集部１３０、実行履歴を取得する実行ファイルリスト１４０、シンボル情報格納部１５０、デバッグ情報格納部１６０、レジスタリスト１７０、実行履歴格納部１８０から構成される。また、同図の左側に従来の実行環境を示す。従来の実行環境は、メモリにロードされた実行ファイル１０、プログラムの実行ファイル２０、ライブラリの実行ファイル３０、プログラム実行部４０から構成されている。
【００３０】
まず、実行ファイル変更部１１０で行う処理手順を説明する。
【００３１】
図４は、本発明の一実施の形態における実行ファイル変更処理のフローチャートである。
【００３２】
ステップ１１０）  まず、実行ファイル変更部１１０は、プログラム実行ファイル２０内に定義されている関数の実行履歴を記録するか否か、ライブラリ実行ファイル３０内のライブラリ関数を記録するか否か、さらに、ライブラリ内で定義されている関数の実行履歴を記録するか否かをユーザに問い合わせ、記録しない場合は、ステップ１３０に移行し、取得する場合は、ステップ１２０に移行する。
【００３３】
ステップ１２０）  プログラム自身がプログラム実行履歴収集装置１００（ロガー）に対して実行した実行ファイル内の関数に関する情報を出力するようにプログラムの実行ファイルを変更する。
【００３４】
ステップ１３０）  ループＡの処理として、まず、初期値ｉ＝０（増分１）、終値をユーザから指定されたアプリケーションを監視するライブラリ数とする。
【００３５】
ステップ１４０）  プログラム自身がプログラム実行履歴収集装置１００に対してライブラリのアプリケーションが実行された関数に関する情報を出力するように、プログラムの実行ファイル２０を変更する。
【００３６】
ループＡの処理として、ｉ＝ｉ＋１として、終値になるまで、ステップ１４０を繰り返す。
【００３７】
ステップ１５０）  ループＢとして、初期値ｉ＝０（増分１）、終値をユーザから指定されたライブラリ内に記述されている関数を監視するライブラリ数とする。
【００３８】
ステップ１６０）  ユーザにより指定されたライブラリ自身がプログラム実行履歴収集装置１００に対して実行したライブラリ内の関数に関する情報を出力するように、ライブラリの実行ファイル３０を変更する。
【００３９】
ループｂの処理として、ｉ＝ｉ＋１として、終値になるまで、ステップ１６０を繰り返す。
【００４０】
図５は、本発明の一実施の形態における実行ファイル変更部の概要動作のフローチャートである。
【００４１】
ステップ２０１０）  ディスクからメモリに実行ファイル２０をロードする。
【００４２】
ステップ２０２０）  実行ファイル２０内に定義されている関数の実行履歴を取得する場合は、ステップ２０３０に移行し、取得しない場合は当該処理を終了する。
【００４３】
ステップ２０３０）  ディスクから実行ファイルを読み出す。
【００４４】
ステップ２０４０）  ループＡ'として、静的にリンクされる関数のシンボルテーブルの各レコードに対しての処理を行う。
【００４５】
ステップ２０５０）  レコードがmain関数である場合は、ステップ２０４０に戻り、双でない場合は、ステップ２０６０に移行する。
【００４６】
ステップ２０６０）  シンボル情報をシンボル情報格納部１５０に登録する。
【００４７】
ステップ２０７０）  メモリにロードされた実行ファイル中に登録した関数を呼び出す機械語命令があるかを判定し、ある場合は、ステップ２０８０に移行し、ない場合は、ステップ２０１２０に移行する。
【００４８】
ステップ２０８０）  メモリにロードされた実行ファイルの関数を読み出す機械語命令を実行履歴収集部１３０を実行する命令と置き換える。
【００４９】
ステップ２０９０）  シンボル情報格納部１５０に、メモリ上の実行ファイルを変更した箇所に着いての情報を登録する。
【００５０】
ステップ２０１００）  メモリにロードされた実行ファイル中に、実行ファイルを変更した箇所へ分岐する機械語命令があるかを判定し、ある場合は、ステップ２０１１０に移行し、ない場合は、ステップ２０７０に移行する。
【００５１】
ステップ２０１１０）  分岐する命令を、変更処理にあわせ、分岐先のアドレスを修正し、ステップ２０１００に移行する。
【００５２】
ステップ２０１２０）  デバッグ情報取得部１２０（図８）の処理を行う。
【００５３】
これにより、プログラム実行部４０がmain関数を実行して処理を終了する。
【００５４】
上記のプログラム実行履歴収集装置１００の実行ファイル変更部１１０の処理を詳しく説明する。
【００５５】
図６は、本発明の一実施の形態における実行ファイル変更部の詳細動作のフローチャートである。
【００５６】
まず、実行ファイル変更部１１０に、実行履歴を取得する実行ファイルリストが格納されたメモリまたはディスク１４０から処理対象が選択されると、プログラムの実行ファイル２０がロードされるものとする。
【００５７】
ステップ１２１０）  ユーザがプログラムを起動すると、ディスクからメモリにプログラムをロードする。
【００５８】
ステップ１２２０）  実行履歴を取得する実行ファイルリスト（メモリ）１４０から実行ファイル２０内に定義されている関数の実行履歴を取得するか否かの情報を取得する。なお、システムの環境変数から、実行ファイル２０内に定義された関数を取得するか否かを取得する。このとき、以下の２つの情報も取得する。
【００５９】
・動的リンク時に使用するライブラリのＡＰＩの実行履歴を取得するライブラリ名；
・動的リンクされるライブラリ内で定義されている関数の実行履歴を取得するライブラリ名：
ディスクに設定ファイルを作成し、設定ファイルからこれらの情報を読み出す方式にすることもできる。
【００６０】
ステップ１２３０）  実行ファイル２０内に定義されている関数の実行履歴を取得するか否かの問い合わせとして、実行ファイル２０の静的リンク（ＥＬＦの.symtabセクションに定義されている）関数の実行履歴を取得するか判定し、取得する場合はステップ１２４０に移行し、取得しない場合は処理を終了する。
【００６１】
ステップ１２４０）  ディスクから実行ファイル２０を読み出す。
【００６２】
ステップ１２５０）  次に、関数の静的シンボル情報についての処理として、ディスクから読み出した実行ファイル２０内の静的シンボルテーブル（ELFの.symtabセクション）から関数に関するシンボル数を取得する（symnum←静的リンク関数の数）。
【００６３】
ステップ１２６０）  初期値をｉ＝０とし、ｉ＝symnumとするループＡの処理を行う。
【００６４】
ステップ１２７０）  静的シンボルテーブルのｉ番目のシンボル情報を取得する（symbol←ｉ番目のシンボル情報）。
【００６５】
ステップ１２８０）  symbolが関数のシンボル情報かを判定し、そうであればステップ１２９０に移行し、そうでない場合はステップ１２６０に移行する。
【００６６】
ステップ１２９０）  symbol がmain関数のシンボル情報かを判定し、そうであれば、ステップ１２６０に移行し、そうでなければステップ１２１００に移行する。
【００６７】
ステップ１２１００）  取得したシンボル情報をシンボル情報格納部１５０に登録する。シンボル情報格納部１５０に登録する情報は、関数名とマッピングされるアドレスである。
【００６８】
ステップ１２１１０）  メモリにロードされた実行ファイル１０のプログラムの機械語命令（ELFの.textセクション）内にシンボル情報格納部１５０に登録していない、symbolを呼び出す機械語命令（i.e. call命令、jmp命令等）があるかを判定し、ある場合は、ステップ１２１３０に移行する。ない場合はステップ１２１７０に移行する。
【００６９】
ステップ１２１２０）  メモリにロードされた実行ファイル１０のsymbolを呼び出す機械語命令を実行履歴収集部１３０を実行する命令と置き換える。
【００７０】
ステップ１２１３０）  シンボル情報格納部１５０に以下の情報を登録する。
【００７１】
・symbolを呼び出す命令のアドレス；
・置き換えた元の機械語命令；
・置き換えた後のリターンアドレス（関数実行履歴取得部を実行する命令の次の命令のアドレス）；
ステップ１２１４０）  「置き換えた元の機械語命令」に、「置き換えた元の機械語命令」の次の命令のアドレスにジャンプする命令（jmp）を追加する。
【００７２】
ステップ１２１５０）  メモリにロードされた実行ファイル１０のプログラムの機械語命令（ELFの.textセクション）内に置き換えられた命令にjmpする機械語命令があるかを判定し、ある場合は、ステップ１２１６０に移行し、ない場合は、ステップ１２１１０に移行する。
【００７３】
ステップ１２１６０）  メモリにロードされた実行ファイル１０のジャンプ(jmp)する機械語命令のオペランドとなるアドレスの値を、シンボル情報格納部１５０に登録した「置き換えた元の機械語命令」のアドレスに置き換え、ステップ１２１５０に戻る。
【００７４】
ステップ１２１７０）  デバッグ情報取得部１２０の処理を行い、プログラム実行部４０がmain関数を実行して処理を終了する。
【００７５】
これにより出力される結果を図７に示す。シンボル情報格納部１５０には、関数名とマッピングされるアドレスが格納される。ここで、マッピングされるアドレスとしては、
・関数を呼び出す命令のアドレス；
・置き換えた元の機械語命令；
・置き換えた後のリターンアドレス；
等である。
【００７６】
次に、プログラム実行履歴収集装置１００のデバック情報取得部１２０の動作を詳細に説明する。デバッグ情報取得部１２０は、実行された関数の引数、返り値の情報を、正確に取得するために必要となる情報（返り値や引数の型情報、引数の格納場所）を取得する処理部である。
【００７７】
なお、以下の説明における「実行ファイル」とは、プログラムの実行ファイル２０、ライブラリの実行ファイル３０の両者を指すものとする。
【００７８】
また、「コンパイルユニット」とは、ソースファイルの情報である。コンパイルユニットは、ソースファイルで定義されている関数、グローバル変数、構造体などについて、名前、型情報、使用するレジスタ、使用するメモリの位置などの情報が関連付けて格納されている。
【００７９】
当該デバッグ情報取得部１２０には、プログラムの実行のファイルが入力値となる。図１０にデバッグ情報の例を示す。サンプルソースコード（ａ）をＧＣＣでコンパイルした場合、func()のデバッグ情報は、（ｂ）ＧＣＣが付加するfunc()についてのデバッグ情報（ＤＷＡＲＦ）となる。
【００８０】
図８は、本発明の一実施の形態におけるデバッグ情報取得部の概要動作のフローチャートである。
【００８１】
ステップ２１１０）  ディスクから実行ファイル２０，３０を読み出す。
【００８２】
ステップ２１２０）  実行ファイル２０，３０にデバッグ情報が含まれているかを判定し、含まれている場合には、ステップ２１３０に移行し、含まれていない場合は当該処理を終了する。
【００８３】
ステップ２１３０）  デバッグ情報格納部１６０にデバッグ位置情報を登録する。
【００８４】
ステップ２１４０）  登録していないコンパイルユニットの情報があるかを判定し、ある場合はステップ２１５０に移行し、ない場合は、当該処理を終了する。
【００８５】
ステップ２１５０）  デバッグ情報格納部１６０に、コンパイルユニットのデバッグ情報を登録する。
【００８６】
ステップ２１６０）  取得したコンパイルユニットについて、登録していない関数の情報があるかを判定し、ある場合はステップ２１７０に移行し、無い場合はステップ２１４０に移行する。
【００８７】
ステップ２１７０）  デバッグ情報格納部１６０に関数のデバッグ情報を登録する。
【００８８】
ステップ２１８０）  取得した関数について登録していない引数の情報があるかを判定し、ある場合はステップ２１９０に移行し、無い場合はステップ２１６０に移行する。
【００８９】
図９は、本発明の一実施の形態におけるデバッグ情報取得部の詳細動作のフローチャートである。
【００９０】
ステップ１３０１０）  ディスクから実行ファイル２０，３０を読み出す。
【００９１】
ステップ１３０２０）  実行ファイル２０，３０にデバッグ情報が含まれているかを判定する。ここで、デバッグ情報とは、変数などの型情報であり、この情報が含まれているか否かを判定する。含まれている場合はステップ１３３０に移行し、含まれていない場合はその処理を終了する。
【００９２】
ステップ１３３０）  引数の値を正確に取得するため、実行中に格納場所が変更される場合の、引数の格納場所を示す情報を取得するために、実行ファイル２０，３０のデバッグ位置情報テーブル（.debug_locセクション）にデバッグ情報格納部１６０に登録されていないレコードがあるかを判定し、ある場合はステップ１３４０に移行し、ない場合はステップ１３６０に移行する。
【００９３】
ステップ１３４０）  登録されていないレコードを取得する。
【００９４】
ステップ１３５０）  デバッグ情報格納部１６０に取得したレコード内の情報を登録し、ステップ３０３に戻る。登録する情報は、
・オフセット；
・有効アドレスの範囲；
・格納場所（レジスタ名、ベースポインタからの距離）；
である。
【００９５】
ステップ１３６０）  引数の値を正確に取得するため、引数、返り値の型情報と、引数の格納場所を示す情報を取得する。このとき、実行ファイル２０，３０のデバッグ情報テーブル（.debug_infoセクション）に、デバッグ情報格納部１６０に登録していないコンパイルユニットレコードがあるかを判定し、ある場合はステップ１３７０に移行し、ない場合は処理を終了する。
【００９６】
ステップ１３７０）  デバッグ情報テーブルから登録していないコンパイルユニットのレコードを取得する（ｃｕ←取得したコンパイルユニットのレコード）。
【００９７】
ステップ１３８０）  デバッグ情報格納部１６０に、ｃｕ内の情報を登録する。登録する情報は、
・ソースファイル名；
・コンパイル時のディレクトリ名；
である。
【００９８】
ステップ１３９０）  実行ファイル２０，３０のデバッグ情報テーブル（.debug_infoセクション）にデバッグ情報格納部１６０に登録していないｃｕに関連付けて格納されている関数のレコードがあるかを判定し、ある場合はステップ１３１００に移行し、ない場合はステップ１３６０に移行する。
【００９９】
ステップ１３１００）  ｃｕに関連付けて格納されている関数のうち、登録していない関数のレコードを取得する（function←取得した関数のレコード）。
【０１００】
ステップ１３１１０）  デバッグ情報格納部１６０にfunction内の情報を登録し、ステップ１３１２０に移行する。登録する情報は、
・関数名；
・マッピングされるアドレス範囲；
・ソースファイルに記述されている位置；
・返り値の型情報；
である。
【０１０１】
ステップ１３１２０）  実行ファイル２０，３０のデバッグ情報テーブル(.debug_infoセクション)にデバッグ情報格納部１６０に登録していないfunctionの引数のレコードがあるかを判定し、ある場合はステップ１３１３０に移行し、ない場合は、ステップ１３９０に移行する。
【０１０２】
ステップ１３１３０）  functionの引数のうち、登録していない引数のレコードを取得する（argument←取得した引数のレコード）。
【０１０３】
ステップ１３１４０）  デバッグ情報格納部１６０にargument内の情報を登録し、ステップ１３１２０に移行する。登録する情報は、
・引数名；
・ソースファイルに記述されている位置；
・型情報；
・値の格納場所（レジスタ名、ベースポインタからの距離、デバッグ位置情報テーブルのオフセット）；
である。関数を実行中に格納場所が変更されない変数や引数の「値の格納場所」には、「レジスタ名」、「ベースポインタから距離」がデバッグ情報テーブルに登録されている。変更される変数や引数の「値の格納場所」には、「デバッグ位置情報テーブルのオフセット」がデバッグ情報に登録されている。「レジスタ」は、値が格納されているレジスタを示す。「ベースポインタからの距離」は、ベースポインタから距離、つまり、メモリ上の位置を示す。
【０１０４】
上記の図９に示すデバッグ情報取得部１２０の処理により、図１１に示すデータがデバッグ情報格納部１６０に格納される。
【０１０５】
次に実行ファイル２０，３０を変更した後に、プログラムを実行し、実行履歴収集部１３０が実行履歴を取得する処理について説明する。
【０１０６】
図１２は、本発明の一実施の形態における実行履歴収集部の概要動作のフローチャートである。
【０１０７】
ステップ２２１０）  レジスタリスト１７０にプログラムの実行状態を保持する。
【０１０８】
ステップ２２２０）  実行しているプログラムにデバッグ情報が付加されているかを判定し、付加されている場合には、ステップ２２６０に移行し、付加されていない場合はステップ２２３０に移行する。
【０１０９】
ステップ２２３０）  実行履歴格納部１８０に実行した関数の情報を登録する。
【０１１０】
ステップ２２４０）  保持したプログラムの状態を復元する。
【０１１１】
ステップ２２５０）  フックした関数に対してjmp命令を実行し、処理を終了する。
【０１１２】
ステップ２２６０）  ステップ２２２０において、実行しているプログラムにデバッグ情報が付加されている場合は、実行しようとした関数について、引数を取得する。
【０１１３】
ステップ２２７０）  実行履歴格納部１８０に実行された引数の情報を登録する。
【０１１４】
ステップ２２８０）  保持したプログラムの状態を保持する。
【０１１５】
ステップ２２９０）  フックした関数に対してcall命令を実行する。
【０１１６】
ステップ２２１００）  レジスタリスト１７０にプログラムの実行状態を保持する。
【０１１７】
ステップ２２１１０）  実行履歴格納部１８０に実行した関数についての情報を登録する。
【０１１８】
ステップ２２１２０）  保持したプログラムの状態を復元する。
【０１１９】
ステップ２２１３０）  ret命令を実行し、当該処理を終了し、プログラム実行部に制御を移行する。
【０１２０】
図１３は、本発明の一実施の形態における実行履歴収集部の詳細動作のフローチャートである。
【０１２１】
ステップ１４１０）  プログラム実行部４０が履歴を取得する関数を実行すると、実行履歴収集部１３０は、メモリ上のレジスタリスト１７０に汎用レジスタとインデックスレジスタを退避し、現状のプログラムの実行状態を保持する。
【０１２２】
例えば、Intel x86アーキテクチャでは「汎用レジスタ」は、
−eax，ebx，ecx，edx
であり、「インデックスレジスタ」は、
−esi，edi
である。
【０１２３】
ステップ１４２０）  デバッグ情報がプログラムに付加されていたかを確認するために、デバッグ情報格納部１６０にフックされた関数のレコードが登録されているかを判定し、登録されている場合はステップ１４１１０に移行し、登録されていない場合は、ステップ１４３０に移行する。
【０１２４】
ステップ１４３０）  シンボル情報格納部１５０からフックされた関数のレコードを読み出す。
【０１２５】
ステップ１４４０）  実行された関数に関する情報として、情報を実行履歴格納部１８０に登録するために、読み出したレコードの関数名、マッピングされるアドレスを実行履歴格納部１８０に登録する。
【０１２６】
ステップ１４５０）  スタックレジスタ、ベースレジスタをＳＴＡＲＴ時の状態に戻す。
【０１２７】
ステップ１４６０）  レジスタリスト１７０から汎用レジスタとインデックスレジスタを復元する。
【０１２８】
ステップ１４７０）  「置き換えた元の機械語命令」が２命令以上である場合は、ステップ１４８０に移行し、そうでない場合は、ステップ１４９０に移行する。
【０１２９】
ステップ１４８０）  メモリ上のスタックの戻り値を「置き換えた元の機械語命令」の実行履歴取得部を実行する命令の次の命令に変更する。
【０１３０】
ステップ１４９０）  フックした関数に対してjmp命令を実行する。これにより特定のプログラムの実行状態を復元する。
【０１３１】
ステップ１４１１０）  ステップ１４２０において、デバッグ情報格納部１６０にフックされた関数のレコードが登録されている場合は、実行された関数の引数の値を取得するために、デバッグ情報格納部１６０から、フックした関数のレコード、フックした関数の引数のレコードを取得する。
【０１３２】
ステップ１４１２０）  値を取得していない引数のレコードがあるかを判定し、ある場合は、ステップ１４１３０に移行し、ない場合はステップ１４１４０に移行する。
【０１３３】
ステップ１４１３０）  取得した引数のレコードの情報を用いて、メモリ、または、レジスタリスト１７０から引数の値を取得し、ステップ１４１２０に戻る。
【０１３４】
ステップ１４１４０）  実行された関数に関する情報を実行履歴格納部１８０に登録する。登録される情報は、
・フックした関数の関数名；
・フックした関数のマッピングされるアドレス；
・取得した引数；
である。
【０１３５】
ステップ１４１５０）  取得した引数のうち、「値の格納場所」がメモリ上となる引数があるかを判定し、ある場合は、ステップ１４１６０に移行し、ない場合はステップ１４１８０に移行する。
【０１３６】
ステップ１４１６０）  スタックポインタレジスタの値を引数が格納されるサイズだけずらす。
【０１３７】
ステップ１４１７０）  スタックポインタレジスタから次に関数を呼び出した後のベースポインタレジスタの値を推定し、メモリに保存する。
【０１３８】
ステップ１４１８０）  実行履歴取得部１３０がメモリに格納していない「値の格納場所」がメモリとなる引数があるかを判定し、ある場合はステップ１４１９０に移行し、ない場合はステップ１４２００に移行する。
【０１３９】
ステップ１４１９０）  「値の格納場所」と、推定したベースポインタレジスタの値から、メモリの適切なアドレスに、取得した引数の値を格納し、ステップ１４１８０に戻る。
【０１４０】
ステップ１４２００）  メモリ上のレジスタリスト１７０から汎用レジスタとインデックスレジスタを復元する。
【０１４１】
ステップ１４２１０）  フックした関数に対してcall命令を実行する。
【０１４２】
ステップ１４２２０）  現状のプログラムの実行状態を保持するため、メモリ上のレジスタリスト１７０に、汎用レジスタとインデックスレジスタを退避する。
【０１４３】
ステップ１４２３０）  取得した関数のレコードを用いて、汎用レジスタ、または、浮動小数点レジスタから関数の返り値を取得する。
【０１４４】
ステップ１４２４０）  プログラム実行履歴格納部１８０に、実行した関数を登録する。詳しくは、返り値を、ステップ１４１４０で登録したレコードと関連付けて、プログラム実行履歴格納部１８０に登録する。
【０１４５】
ステップ１４２５０）  メモリ上のスタックの戻り値を「置き換えた元の機械語命令」の２番目の命令に変更する。
ステップ１４２６０）  シンボル情報格納部１５０からフックされた関数のレコードを読み出す。
【０１４６】
ステップ１４２７０）  保持したプログラムの実行状態を復元するために、メモリ上のレジスタリスト１７０から汎用レジスタとインデックスレジスタを復元する。
【０１４７】
ステップ１４２８０）  ret命令を実行し、プログラム実行部４０に制御を移行する。
【０１４８】
さらに、図４では、プログラム起動時にプログラムを変更しているが、実行中のプログラムに対しても、メモリにロードされた実行ファイル１０に実行履歴を取得する処理を挿入することができる。挿入する処理を以下に示す。
【０１４９】
図１４は、本発明の一実施の形態における実行中のプログラムの実行ファイルを変更する処理のフローチャートである。
【０１５０】
ステップ１９１０）  まず、実行ファイル変更部１１０が、プログラムに対してシグナル（SIGSTOP）を配送することにより、実行プログラムを停止する。
【０１５１】
ステップ１９２０）  メモリにロードされた実行プログラムを変更する。
【０１５２】
ステップ１９３０）  実行ファイル変更部１１０が、プログラムに対してシグナル（SIGCONT）を配送し、実行プログラムを継続する。
【０１５３】
このとき、従来のデバッガでは、実行ファイルにブレークポイントを設定し、制御をデバッガに強制的に移行させる。しかし、本発明は、プログラム自身が関数の実行履歴を出力するように、プログラムの実行ファイルを変更することにより、ブレークポイントを設定して関数の実行履歴を出力するより、出力に必要となる時間を短くすることができる。
【０１５４】
［プログラム実行履歴分割装置］
次に、プログラム実行履歴分割装置について説明する。
【０１５５】
ユーザが出力結果まで想定できる入力値を用いて、プログラムを実行し、実行履歴を取得する。この取得した実行履歴を実行された関数のコールスタックの深さと、出現パターンに着目し、関数コールシーケンスの局所を関数ブロックと定義する。
【０１５６】
以下に実行履歴の区分処理について説明する。
【０１５７】
図１５は、本発明の一実施の形態におけるプログラム実行履歴分割装置の構成を示す。
【０１５８】
プログラム実行履歴分割装置２００は、実行履歴を区分する処理を行う。この区分は、関数のコールスタックの深さの値が小さくなる箇所に着目している。それは、スタックのコールスタックの深さの値が、前後と比較し、最も大きくなる関数というのは、実行しているプログラムのサービスを提供するための処理であると言える。その前のコールスタックの深さの値が大きくなっていく部分の関数コールシーケンスは、このサービスを提供する関数の前処理をしている箇所であるといえる。そのため、関数のコールスタックの深さが小さくなる部分で区切り、これを関数ブロックとして扱う。このとき、関数ブロックのシーケンスにおいて、同一のシーケンスが存在した場合、同一のものが存在するシーケンスを１つの関数ブロックとする。当該関数ブロックをプログラムの出力パターンとする。
【０１５９】
プログラム実行履歴分割装置２００は、実行履歴読込み部２１０、実行履歴区分部２２０、関数ブロック生成部２３０、関数ブロック登録部２４０から構成される。
【０１６０】
図１６は、本発明の一実施の形態における実行履歴区分部の概要動作のフローチャートである。
【０１６１】
ステップ２３１０）  ループＣ'として、実行履歴格納部１８０から各実行履歴を読み出す。
【０１６２】
ステップ２３２０）  サービスを提供している処理を検索し、検索できた場合は、ステップ２３３０に移行し、検索できない場合は、次の実行履歴を読み出す。
【０１６３】
ステップ２３３０）  検索されたサービスを提供している処理と、その前処理を１つの処理として関数ブロックテーブル２５０に登録する。
【０１６４】
ステップ２３４０）  ループＣ'が終了したら、最後の処理を関数ブロックテーブル２５０に登録する。
【０１６５】
図１７は、本発明の一実施の形態における実行履歴区分部の詳細動作のフローチャートである。
【０１６６】
ステップ３１０）  初期値として、ｉｄ＝０，ｈｅａｄ＝０とする。
【０１６７】
ステップ３２０）  初期値ｉ＝０（増分１）、終値を、取得したプログラムの実行履歴に含まれる関数の個数とし、以下のループ（ループＣ）処理を行う。
【０１６８】
ステップ３３０）  実行履歴格納部１８０から実行履歴が読み込まれると、実質的にサービスを提供している処理を検索するために、関数のｉ番目に呼ばれた関数より（ｉ＋１）番目に呼ばれた関数の方がコールスタックの深さが浅いかを判定し、浅い場合はステップ３４０に移行し、深い場合は、終値（取得したプログラムの実行履歴に含まれる関数の個数）になるまでステップ３２０に移行する。
【０１６９】
ステップ３５０）  ｉｄ＝ｉｄ＋１，ｈｅａｄ＝ｉ＋１とし、ステップ３３０の処理を繰り返す。
【０１７０】
ステップ３６０）  head番目からｉ番目に呼ばれた関数を１つのブロックとし、関数ブロックＩＤ番号をｉｄとして、関数ブロックテーブル２５０に登録する。
【０１７１】
上記の具体例として、サンプルソースコードと、このコードを実行したときの関数コールシーケンスの区切り方を図１８に示す。このとき、関数コールシーケンスを区切った箇所を関数ブロックとする。
【０１７２】
関数ブロック生成部２３０は、比較対象となる関数パターンを生成する。上記で作成した関数ブロックについて、複数回実行される処理を検索し、比較対象となる関数パターンを１つの関数ブロックにすることによって、関数パターンを削減する。また、複数回繰り返される処理を関数ブロックにすることにより、その処理が一連の処理であるという信頼性を高めることができる。
【０１７３】
関数ブロック同士を比較し、関数ブロック内の関数が順序も含め同一である関数ブロックを検索する。さらに、一致した関数ブロックの次の関数ブロックについても関数ブロック内の関数が順序も含め同一の関数ブロックであるか調べ、この調べる処理を同一の関数ブロックである間、繰り返す。同一の関数ブロックが存在する場合、同一であった一連の関数ブロックを１つの関数ブロックとして扱う。さらに、作成した関数ブロックには、関数ブロックを一意に特定できる関数ブロックＩＤを付与する。この処理を図１９、２０に示す。
【０１７４】
図１９は、本発明の一実施の形態における関数ブロック生成部の概要動作のフローチャートである。
【０１７５】
ステップ２４１０）  ループＤ'として、図１６で作成した各関数ブロックに対しての処理を行う。
【０１７６】
ステップ２４２０）  関数の実行パターンとして、関数ブロックを作成する。
【０１７７】
ステップ２４３０）  作成した関数ブロックを関数ブロックテーブル２５０に登録する。
【０１７８】
全ての関数ブロックを処理するまで、ループＤ'として、上記の処理を繰り返す。
【０１７９】
上記の動作を以下で詳細に説明する。
【０１８０】
図２０は、本発明の一実施の形態における関数ブロック生成部の詳細動作のフローチャートである。以下では、関数ブロック生成部２３０内のメモリに、図２１（ｂ）に示すような関数ブロック一致リストを有するものとする。
【０１８１】
ステップ４１０）  ｉｄ＝関数ブロックの個数とする。
【０１８２】
ステップ４２０）  初期値としてｉ＝０（増分１）、終値をｉｄとする。
【０１８３】
ステップ４３０）  関数ブロック一致リストを初期化する。
【０１８４】
ステップ４４０）  ループＥの初期値としてｋ＝ｉ（増分１）、終値をｉｄとする。
【０１８５】
ステップ４５０）  関数ブロックＩＤ番号がｉの関数ブロックと、関数ブロックＩＤ番号がｋの関数ブロックを比較し、ブロック内の関数名が順序も含め、完全に一致するか判定し、一致する場合は、ステップ４６０に移行し、ループＥの処理を繰り返す。
【０１８６】
ステップ４６０）  ループＦの初期値としてnum＝１（増分１）、終値＝（ｋ−１）とする。
【０１８７】
ステップ４７０）関数ブロックＩＤ番号が（ｉ＋num）の関数ブロックと関数ブロックＩＤ番号が（ｋ＋num）の関数ブロックを比較し、ブロック内の関数名が順序も含め、完全に一致するか判定し、一致する場合は、num=num＋１とし、ループＦの処理を終値（num=k-1）になるまで繰り返し、不一致の場合はステップ４８０に移行する。
【０１８８】
ステップ４８０）  関数ブロック一致リストにＩＤがｋの関数ブロックと、一致したブロック個数であるnumの値を登録したノードを追加し、ループＥの処理をｋ＝ｉｄとなるまで繰り返す。
【０１８９】
ステップ４９０）  関数ブロック一致リストにノードがあるかを判定し、ある場合は、ステップ４１００に移行し、ない場合は、ループＤの処理をｉ＝ｉｄになるまで繰り返す。
【０１９０】
ステップ４１００）  関数ブロック一致リストの各ノードを比較し、関数ブロックＩＤ番号がｉの関数ブロックと、最も長く一致した関数ブロックについて、一致したブロック数を１つのブロックとして連結させたものを１つのブロックとする。
【０１９１】
ステップ４１１０）  連結したブロックに対応するブロックを削除し、作成したブロックを関数ブロックテーブル２５０に登録する。  ループＤの処理として、ｉ＝ｉ＋１とし、ｉ＝ｉｄとなるまで、ループＤの処理を繰り返す。
【０１９２】
図２１（ｂ）に示す関数ブロック一致リストは、この検索した結果が登録されたものである。この関数ブロック一致リストを用いて、複数の関数ブロックを１つに纏めるか否かを判断する。図２１（ａ）のシーケンス２は、関数ブロック一致リストを用いて、複数のブロックを１つのブロックに纏めた結果となる関数ブロックシーケンスであり、これが関数ブロック登録部２４０を介して関数ブロックテーブル２５０に登録される。
【０１９３】
上記のプログラム実行履歴分割装置２００では、プログラムが実行した関数コールシーケンスをユーザにとって意味のある処理単位で区切ることにより、どの処理にバグが存在するのか、ユーザに知らせることができる。そのため、デバッグのためにユーザがソースコードを見る範囲を絞らせることができ、バグを発見するまでの時間を短くすることの手助けとなる。
【０１９４】
［プログラム実行履歴比較装置］
上記のプログラム実行履歴分割装置２００によって作成した関数ブロックが、ユーザが想定しているプログラムの実行結果であると定義する。このため、エラーが発生したプログラムの関数コールシーケンスに、作成した関数ブロックとは異なる関数が実行されている箇所、これらの箇所においても、関数の呼び出し関係が同一となる関数が存在しない関数、特異性が高い関数にバグが存在する可能性が高い。これは、プログラムのバグとは、開発者の想定していない入力値がプログラムに入力されることによって、顕在化するためである。さらに、プログラムの開発や検証で使用している計算機の性能と、このプログラムを実行している計算機の性能が異なることによっても顕在化する。
【０１９５】
以下、特異性が高い関数を検索するためのプログラム実行履歴比較装置について説明する。
【０１９６】
プログラム実行履歴比較装置は、プログラム実行履歴分割装置２００で作成したプログラムの出力パターンと、エラーが発生したプログラムの出力を比較する。このとき、出力パターンが存在せず、かつ、エラーが発生したプログラムの出力中にも、複数存在しないコールパターンを検索し、出現頻度が低い関数コールパターンを、強調して表示する。
【０１９７】
図２２は、本発明の一実施の形態におけるプログラム実行履歴比較装置の構成を示す。
【０１９８】
同図に示すプログラム実行履歴比較装置３００は、関数ブロック読込み部３１０、プログラム実行履歴収集部３２０、実行履歴データ格納部３３０、関数ブロックと実行履歴の比較部３４０、関数ブロック登録部３５０、関数登録部３６０、比較結果格納テーブル３７０から構成される。
【０１９９】
図２３は、本発明の一実施の形態におけるプログラム実行履歴比較装置の動作を示す図である。
【０２００】
ステップ８１０）  関数ブロック読込み部３１０は、関数ブロックテーブル２５０から作成したテーブルを読み込む。
【０２０１】
ステップ８２０）  次に、プログラム実行部４０で関数ブロックを作成したプログラムと同一のプログラムが実行されると、プログラム実行履歴収集部３２０は、プログラムの実行履歴を取得できるかを判定し、できる場合はステップ８３０に移行し、取得でできない場合は、プログラムの実行履歴と関数ブロックの比較処理を終了する。
【０２０２】
ステップ８３０）  プログラム実行履歴収集部３２０は、プログラムの実行履歴を取得する。
【０２０３】
ステップ８４０）  実行履歴データ格納部３３０は、取得した実行履歴の、実行された時刻、関数名、引数、返り値、コールスタックの深さを取得し、格納する。
【０２０４】
ステップ８５０）  関数ブロックと実行履歴の比較部３４０は、読み込んだ関数ブロックと、実行履歴データ格納部３３０から取得した関数実行シーケンスを比較し、一致する場合は、ステップ８６０に移行し、一致しない場合は、ステップ８７０に移行する。
【０２０５】
ステップ８６０）  一致する場合は、一致した関数ブロックと関数ブロック内の関数に関する情報を比較結果格納テーブルに３７０に格納する。
【０２０６】
ステップ８７０）  一致しない場合は、実行された関数に関する情報（コールスタックの深さ、関数名、引数、返り値）を比較結果格納テーブル３７０に格納する。
【０２０７】
これにより、実行中のプログラムにプログラムエラーが発生した場合は、この比較結果格納テーブル３７０から特異性の高い関数、または、関数ブロックを選択し、ユーザに提示する。
【０２０８】
次に、比較結果格納テーブル３７０に、関数と関数ブロックが登録された場合と関数ブロックのみが登録された場合について説明する。
【０２０９】
図２４は、本発明の一実施の形態における比較結果格納テーブルに関数と関数ブロックが登録された場合の例を示す。
【０２１０】
図２４では、関数ブロックと関数実行シーケンスを比較した結果、一致する関数ブロックと、関数ブロックに一致しなかった関数に分類された場合の特異性の高い関数の発見手段である。特異性の高い関数は、関数ブロックと一致しない箇所にあると考えられる。そのため、関数ブロックと一致しなかった関数の中から、特異性の高い関数を選択する。これらの関数の中においても、呼び出し関係が同一となる実行パスが存在するか否かを検索する。図２４では、関数Ａ⇒関数Ｂという実行パスが同一となる箇所と、関数Ｃのみがブロックの間に挟まれて存在する箇所がある。このとき、複数実行されている関数Ａ⇒関数Ｂという実行パスより、１回のみ実行されている関数Ｃの特異性の方が低いと考えられる。ユーザに特異性が低い箇所から順に提示することよって、バグが存在する関数をより早く提示することができる。
【０２１１】
図２５は、本発明の一実施の形態における比較結果格納テーブルに関数ブロックのみが登録された場合の例を示す。
【０２１２】
図２５の例は、関数ブロックと関数実行シーケンスを比較した結果、その結果が関数ブロックのみに分類された場合における、特異性の高い関数の発見手段である。実行回数が最小値となる関数ブロックを検索する。図２５では、関数ブロックＡ，Ｂ，Ｃのうち、関数ブロックＣが実行回数が最も少ない。そのため、関数ブロックＣの特異性が高いと定義できる。関数ブロックＣ内のどの関数の特異性が高いかの判断は、引数、返り値を比較し、それぞれの値が、関数ブロックテーブル２５０に登録されていた値と同一であるか否かによってその特異性の高さを判断する。
【０２１３】
上記のプログラム実行履歴分割装置２００は、ユーザが出力結果まで想定できる入力値によって実行した実行履歴を取得し、プログラムの実行履歴の出力パターンを検出する。次に、プログラム実行履歴比較装置３００において、プログラム実行履歴分割装置２００で作成されたプログラムの出力パターンと、エラーが発生したプログラムの出力中にも、出現頻度の低い関数コールパターンを検索し、該関数コールパターンを強調して表示する。これにより、デバッグを行うユーザのスキルに依存せず、エラーが発生してから、このエラーに対応するソースコード上のバグを発見するまでの時間を短くできる。
【０２１４】
なお、上記のプログラム実行履歴収集装置、プログラム実行履歴分割装置、プログラム実行履歴比較装置を一つのデバッグ支援装置として構築することが可能である。
【０２１５】
また、プログラム実行履歴収集装置、プログラム実行履歴分割装置、プログラム実行履歴比較装置の動作をプログラムとして構築し、プログラム実行履歴収集装置、プログラム実行履歴分割装置、プログラム実行履歴比較装置からなる装置として利用されるコンピュータにインストールして実行させる、または、ネットワークを介して流通させることが可能である。
【０２１６】
また、構築されたプログラムをハードディスク装置や、フレキシブルディスク・ＣＤ−ＲＯＭ等の可搬記憶媒体に格納し、コンピュータにインストールする、または、配布することが可能である。
【０２１７】
なお、本発明は、上記の実施の形態に限定されることなく、特許請求の範囲内において種々変更・応用が可能である。
【産業上の利用可能性】
【０２１８】
本発明は、プログラムの開発・実行におけるデバッグに適用可能である。
【０２１９】
また、プログラムのバージョンアップの前と後や、プログラムの動作環境変更の前と後のプログラムの動作の差異を検出して、デグレーションの発生を自動検出する技術等にも適用可能である。
【図面の簡単な説明】
【０２２０】
【図１】本発明の原理構成図である。
【図２】本発明の原理を説明するための図である。
【図３】本発明の一実施の形態におけるプログラム実行履歴収集装置の構成図である。
【図４】本発明の一実施の形態における実行ファイル変更処理のフローチャートである。
【図５】本発明の一実施の形態における実行ファイル変更部の概要動作のフローチャートである。
【図６】本発明の一実施の形態における実行ファイル変更部の詳細動作のフローチャートである。
【図７】本発明の一実施の形態におけるシンボル情報格納部に格納されるデータの例である。
【図８】本発明の一実施の形態におけるデバッグ情報取得部の概要動作のフローチャートである。
【図９】本発明の一実施の形態におけるデバッグ情報取得部の詳細動作のフローチャートである。
【図１０】本発明の一実施の形態における付加されるデバッグ情報（図９に対する入力値）の例である。
【図１１】本発明の一実施の形態におけるデバッグ情報格納部に格納されるデータである。
【図１２】本発明の一実施の形態における実行履歴収集部の概要動作のフローチャートである。
【図１３】本発明の一実施の形態における実行履歴収集部の詳細動作のフローチャートである。
【図１４】本発明の一実施の形態における実行中のプログラムの実行ファイルを変更する処理のフローチャートである。
【図１５】本発明の一実施の形態におけるプログラム実行履歴分割装置の構成図である。
【図１６】本発明の一実施の形態における実行履歴区分部の概要動作のフローチャートである。
【図１７】本発明の一実施の形態における実行履歴区分部の詳細動作のフローチャートである。
【図１８】本発明の一実施の形態における実行履歴区分部の関数コールシーケンスの区切り方の例である。
【図１９】本発明の一実施の形態における関数ブロック生成部の概要動作のフローチャートである。
【図２０】本発明の一実施の形態における関数ブルック生成部の詳細動作のフローチャートである。
【図２１】本発明の一実施の形態における関数ブロック生成の例である。
【図２２】本発明の一実施の形態におけるプログラム実行履歴比較装置の構成図である。
【図２３】本発明の一実施の形態におけるプログラム実行履歴比較装置の概要動作のフローチャートである。
【図２４】本発明の一実施の形態における比較結果格納テーブルに関数と関数ブロックが登録された場合の例である。
【図２５】本発明の一実施の形態における比較結果格納テーブルに関数ブロックのみが登録された場合の例である。
【符号の説明】
【０２２１】
１０  メモリにロードされた実行ファイル
２０  プログラムの実行ファイル
３０  ライブラリの実行ファイル
４０  プログラム実行手段、プログラム実行部
１００  プログラム実行履歴収集手段、プログラム実行履歴収集装置
１１０  実行ファイル変更部
１２０  デバッグ情報取得部
１３０  実行履歴収集部
１４０  実行履歴を取得する実行ファイルリスト（メモリまたはディスク）
１５０  シンボル情報格納部（メモリ）
１６０  デバッグ情報格納部（メモリ）
１７０  レジスタリスト（メモリ）
１８０  実行履歴記憶手段、実行履歴格納部
２００  プログラム実行履歴分割手段、プログラム実行履歴分割装置
２１０  実行履歴読込み部
２２０  実行履歴区分部
２３０  関数ブロック生成部
２４０  関数ブロック登録部
２５０  関数ブロック記憶手段、関数ブロックテーブル
３００  比較手段、プログラム実行履歴比較装置
３１０  関数ブロック読込み部
３２０  プログラム実行履歴収集部
３３０  実行履歴データ格納部
３４０  関数ブロックと実行履歴の比較部
３５０  関数ブロック登録部
３６０  関数登録部
３７０  比較結果記憶手段、比較結果格納テーブル
【図１】
0004763743.tif 000002
【図２】
0004763743.tif 000003
【図３】
0004763743.tif 000004
【図４】
0004763743.tif 000005
【図５】
0004763743.tif 000006
【図６】
0004763743.tif 000007
【図７】
0004763743.tif 000008
【図８】
0004763743.tif 000009
【図９】
0004763743.tif 000010
【図１０】
0004763743.tif 000011
【図１１】
0004763743.tif 000012
【図１２】
0004763743.tif 000013
【図１３】
0004763743.tif 000014
【図１４】
0004763743.tif 000015
【図１５】
0004763743.tif 000016
【図１６】
0004763743.tif 000017
【図１７】
0004763743.tif 000018
【図１８】
0004763743.tif 000019
【図１９】
0004763743.tif 000020
【図２０】
0004763743.tif 000021
【図２１】
0004763743.tif 000022
【図２２】
0004763743.tif 000023
【図２３】
0004763743.tif 000024
【図２４】
0004763743.tif 000025
【図２５】
0004763743.tif 000026