JP2008059402A - リアルタイム診断システムおよびリアルタイム診断方法 - Google Patents
リアルタイム診断システムおよびリアルタイム診断方法 Download PDFInfo
- Publication number
- JP2008059402A JP2008059402A JP2006237087A JP2006237087A JP2008059402A JP 2008059402 A JP2008059402 A JP 2008059402A JP 2006237087 A JP2006237087 A JP 2006237087A JP 2006237087 A JP2006237087 A JP 2006237087A JP 2008059402 A JP2008059402 A JP 2008059402A
- Authority
- JP
- Japan
- Prior art keywords
- function
- trace
- address
- time
- real
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Landscapes
- Debugging And Monitoring (AREA)
Abstract
【課題】 限られたシステムリソースの環境であっても診断データをデバイス上でリアルタイムに集め、障害原因の診断を可能とする。
【解決手段】 アプリケーション(AP)からの関数コールに対して関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、関数が終了する場合に関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数を用いる。それぞれの関数の冒頭に、関数の実行後に戻るべきアドレスをスタックに一時記憶する命令と、入口トレース関数を呼び出して実行する命令を加えておく。APから関数コールがあると、関数の開始時に入口トレース関数を呼び出して関数履歴を取得してリターンレジスタに前記出口トレース関数の呼び出しを設定し、関数に戻って関数本体の内容を実行し、関数の終了時に出口トレース関数を呼び出して関数履歴を取得した後、スタックに一時記憶したアドレスを基にAPに戻る。
【選択図】図1
【解決手段】 アプリケーション(AP)からの関数コールに対して関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、関数が終了する場合に関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数を用いる。それぞれの関数の冒頭に、関数の実行後に戻るべきアドレスをスタックに一時記憶する命令と、入口トレース関数を呼び出して実行する命令を加えておく。APから関数コールがあると、関数の開始時に入口トレース関数を呼び出して関数履歴を取得してリターンレジスタに前記出口トレース関数の呼び出しを設定し、関数に戻って関数本体の内容を実行し、関数の終了時に出口トレース関数を呼び出して関数履歴を取得した後、スタックに一時記憶したアドレスを基にAPに戻る。
【選択図】図1
Description
本発明は、リアルタイムソフトウェアシステムに組み込んで、システムの障害診断に適用されるリアルタイム診断システムおよびリアルタイム診断方法に関する。特に、不具合に関連した生の診断データ収集のオーバーヘッドを従来の操作の中で無視できるレベル(例えば10%以下)まで押さえ、デバイス上でリアルタイムに障害診断ができるリアルタイム診断システムおよびリアルタイム診断方法に関する。
携帯電話などのワイヤレスデバイスの普及が進むにつれ、単なる通話機能だけではなく、いわゆる電子電話帳機能、電子メール通信機能、スケジュール機能、写真撮影機能、着信メロディ機能、テレビジョン画像の受信機能など多種多様な機能が搭載されている。その一方、携帯電話などのワイヤレスデバイスはシステムリソースが限られているため、これら機能を駆使する結果、携帯電話に障害が発生することも多い。
携帯電話などのワイヤレスデバイス上で発生する障害には、様々なレベルがあり、一時的に不安定になる程度の障害のレベルから、復旧のためにメーカーへの持ち込みが必要となる障害のレベルまである。障害の発生をリアルタイムに検知するために障害検知機能を組み込むことが望まれている。
携帯電話などのワイヤレスデバイス上で発生する障害には、様々なレベルがあり、一時的に不安定になる程度の障害のレベルから、復旧のためにメーカーへの持ち込みが必要となる障害のレベルまである。障害の発生をリアルタイムに検知するために障害検知機能を組み込むことが望まれている。
障害検知機能のために携帯電話の通常機能のリアルタイム性に影響を与えるようではユーザーの利便性に影響が及ぶ。そのため、携帯電話の通常機能のリアルタイム性への影響を最小限としつつ障害検知を行なうリアルタイム診断システムが求められている。
ソフトウェアの不具合を診断するために、最も有効になるデータは関数の呼び出し履歴をトレースしたファンクショントレースデータである。
従来のソフトウェア障害検知手法においてファンクショントレースを実行する技術としては特許文献1などに記載されたものが知られていた。当該デバッグ処理方法はリアルタイムを想定したものではなくコンパイルオプションを用いてファンクショントレース用の関数を挿入してデバッグ手法としてコマンドの実行履歴や関数の呼び出し履歴を記録し、ソフトウェアの障害が検知されれば、これらコマンド実行履歴や関数の呼び出し履歴にアクセスし、初期状態に戻してから再び履歴に沿った操作を行い、エラーが起こった直前のコマンドを実行する前の状態を再現するものであった。
従来のソフトウェア障害検知手法においてファンクショントレースを実行する技術としては特許文献1などに記載されたものが知られていた。当該デバッグ処理方法はリアルタイムを想定したものではなくコンパイルオプションを用いてファンクショントレース用の関数を挿入してデバッグ手法としてコマンドの実行履歴や関数の呼び出し履歴を記録し、ソフトウェアの障害が検知されれば、これらコマンド実行履歴や関数の呼び出し履歴にアクセスし、初期状態に戻してから再び履歴に沿った操作を行い、エラーが起こった直前のコマンドを実行する前の状態を再現するものであった。
上記特許文献1、2などは特定の関数をプログラムや関数に挿入して、プログラムの動作管理情報や関数のスタック情報を収集するものである。管理関数はコンパイルオプションによって埋め込まれる。ファンクショントレースの場合は、ファンクショントレースを実行するためファンクショントレース用の関数がコンパイルのオプションにより組み込まれる。コンパイルのオプションによってファンクショントレース用の関数を挿入する手法は、関数の入口と出口の2箇所にファンクショントレース用の関数の呼び出しを入れる。
しかし、コンパイルオプションを使った従来の方式では、システムにかける負荷が非常に大きいため、リアルタイムに適用できる完全なファンクショントレースを実装することが不可能である。コンパイルオプションを使って、ファンクショントレース用の関数を挿入した場合は、各関数に少なくとも8つの命令を挿入し、ARMモードの場合に大抵40バイトのコードを追加することが必要となり、例えば10万個の関数を有するソフトウェアシステムでは4MB分のコードが増えることとなる。また、実行時間に関して、例えば200MHzのプロセッサを搭載したシステム上で挿入したファンクショントレース関数を実行するには20マイクロセカンド以上が必要となってしまい、システムパフォーマンスが3倍から5倍遅くなってしまう。
また、ソフトウェア障害診断としてロジカルエラーの診断が重要であるところ、ソフトウェア上のロジカルエラーを診断するためには関数の引数と返し値は重要なデータとなる。しかし、関数の引数と返し値を記録すること(関数の引数と返し値のトレース)は、上記のコンパイルのオプションを用いたファンクショントレース手法で関数の引数と返し値を取得することができず、また、上記のファンクショントレース同様にデータ量が多くシステムのパフォーマンスに影響するので従来技術ではリアルタイム診断に適用できる適当な手法がなかった。
また、ソフトウェア障害の原因としてメモリリークが挙げられるが、潜在的なメモリリークはよく発生し得る問題である。このメモリリークが発生するとシステムが不安定になったり、アプリケーションが起動できなくなったりする致命的な障害が起きる恐れがある。しかし、従来技術にはリアルタイムシステムにおいて、アプリケーションのどの個所でどの位の量のメモリが何故漏れたかを確実に検出する有効的な方法はなかった。
また、携帯電話などのモバイルシステムの障害診断では、すべてのオペレーションに対してパフォーマンスを測定して評価する必要があるが、多くのオペレーションが短いので従来の計測方法では正確に測ることが困難である。また、オペレーションのレスポンスが遅い場合にそのレスポンスが遅くなる原因を特定するための情報を取得するのが困難であった。
そこで、本発明は、ワイヤレスデバイスなど限られたシステムリソースの環境において、不具合に関連した生の診断データをデバイス上でリアルタイムに集め、その障害が発生した原因の診断を可能とするリアルタイム診断システムおよびリアルタイム診断方法を提供することを目的とする。
上記目的を達成するため、本発明のリアルタイム診断システムは、以下のファンクショントレース手法を用いる。本発明においてファンクショントレースとは、関数の開始と終了の履歴を記録する機能をいい、ファンクショントレース手法とは、この履歴を記録する関数(ファンクショントレース関数)を挿入することを言い、従来のコンパイルオプションを用いた手法と異なり、関数の入口と出口に2つのファンクショントレース用関数を挿入するのでなく、関数の入口だけに関数の開始履歴を記録する入口トレース関数の呼び出しを挿入し、この挿入した入口トレース関数の中で出口トレース関数の呼び出しを設定する。
本発明のリアルタイム診断システムは、アプリケーションと関数を備えたリアルタイムソフトウェアシステムに対して、
前記アプリケーションから前記関数が呼び出しを受けた場合に前記関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、前記関数が終了する場合に前記関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数とを備え、
それぞれの前記関数の冒頭に、前記アプリケーションから呼び出された際に前記関数の実行後に戻るべきアドレスをスタックに一時記憶する命令(str lr, [sp, #4]!)と、前記入口トレース関数を呼び出して実行する命令(bl __mv_functrace_enter)を加え、
前記アプリケーションから前記関数が呼び出されると、前記関数の開始時に前記入口トレース関数を呼び出して前記関数履歴を取得し、前記関数に戻って前記関数本体の内容を実行し、前記関数の終了時に前記出口トレース関数を呼び出して前記関数履歴を取得した後、前記スタックに一時記憶した前記アドレスを手掛かりとして前記アプリケーションに戻ることにより、前記関数履歴のトレース(ファンクショントレース)を実行することを特徴とする。
前記アプリケーションから前記関数が呼び出しを受けた場合に前記関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、前記関数が終了する場合に前記関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数とを備え、
それぞれの前記関数の冒頭に、前記アプリケーションから呼び出された際に前記関数の実行後に戻るべきアドレスをスタックに一時記憶する命令(str lr, [sp, #4]!)と、前記入口トレース関数を呼び出して実行する命令(bl __mv_functrace_enter)を加え、
前記アプリケーションから前記関数が呼び出されると、前記関数の開始時に前記入口トレース関数を呼び出して前記関数履歴を取得し、前記関数に戻って前記関数本体の内容を実行し、前記関数の終了時に前記出口トレース関数を呼び出して前記関数履歴を取得した後、前記スタックに一時記憶した前記アドレスを手掛かりとして前記アプリケーションに戻ることにより、前記関数履歴のトレース(ファンクショントレース)を実行することを特徴とする。
上記構成により、本発明におけるファンクショントレースは、コンパイルオプションを使用せず、前記アセンブリレベルで2つの命令(アセンブリコード)を各関数の冒頭に挿入して実行せしめることにより、例えば200MHzのプロセッサを搭載するシステムならば2マイクロセカンド以内で関数履歴のトレースを実行でき、システムのリアルタイム動作に影響しない水準でソフトウェア障害解析に重要なデータを取得することができる。
上記構成の本発明のリアルタイム診断システムのより具体的な構成は、前記アプリケーションから前記関数を呼び出すアドレスをaddr1、前記関数処理から戻るアドレスをaddr2、前記関数の最初の命令のアドレスをaddr3とし、
前記関数の冒頭に加える命令が、前記アドレスaddr2をスタックに一時記憶するアセンブリ命令(str lr, [sp, #4]!)と前記入口トレース関数を呼び出すアセンブリ命令(bl __mv_functrace_enter)であり、
前記入口トレース関数が前記関数履歴の取得後に、リターンレジスタに前記出口トレース関数の呼び出しを設定する命令(ldr lr, =__mv_functrace_exit)と、前記関数のアドレスaddr3に戻る命令とを備え、
前記関数が実行の最後に前記リターンレジスタに設定されている前記出口トレース関数をプログラムカウンタに入れる仕組みを備え、
前記出口トレース関数が前記関数履歴の取得後に、前記スタックに一時記憶されている前記アドレスaddr2をプログラムカウンタに入れる命令(ldr pc, [sp, #-4])を備え、
前記アプリケーションの前記アドレスaddr1から前記関数の呼び出し実行、前記関数の開始時に前記入口トレース関数の実行、前記アドレスaddr3に戻って前記関数の実行、前記関数の終了時に前記仕組みによって前記出口トレース関数の実行を経て、前記アプリケーションのアドレスaddr2に戻ることにより前記ファンクショントレースを実行することを特徴とする。
前記関数の冒頭に加える命令が、前記アドレスaddr2をスタックに一時記憶するアセンブリ命令(str lr, [sp, #4]!)と前記入口トレース関数を呼び出すアセンブリ命令(bl __mv_functrace_enter)であり、
前記入口トレース関数が前記関数履歴の取得後に、リターンレジスタに前記出口トレース関数の呼び出しを設定する命令(ldr lr, =__mv_functrace_exit)と、前記関数のアドレスaddr3に戻る命令とを備え、
前記関数が実行の最後に前記リターンレジスタに設定されている前記出口トレース関数をプログラムカウンタに入れる仕組みを備え、
前記出口トレース関数が前記関数履歴の取得後に、前記スタックに一時記憶されている前記アドレスaddr2をプログラムカウンタに入れる命令(ldr pc, [sp, #-4])を備え、
前記アプリケーションの前記アドレスaddr1から前記関数の呼び出し実行、前記関数の開始時に前記入口トレース関数の実行、前記アドレスaddr3に戻って前記関数の実行、前記関数の終了時に前記仕組みによって前記出口トレース関数の実行を経て、前記アプリケーションのアドレスaddr2に戻ることにより前記ファンクショントレースを実行することを特徴とする。
上記構成により、アドレスaddr1における関数の呼び出しに対して、入口トレース関数のみを関数の入口に挿入して関数の呼び出し・実行の入口(開始時)と出口(終了時)に関数履歴を取得しつつ、関数実行後に戻るべきアドレスaddr2に戻って来ることができる。
ここで、前記入口トレース関数は以下の構成とする。つまり、前記リターンレジスタにあるアドレスaddr3をスタックに保存せしめる命令(str lr, [sp, #-4]!)と、前記関数開始時の最初の4つのレジスタの内容をスタックに保存せしめる命令(stmfd sp!, {r0, r1, r2, r3})と、前記関数の開始時刻とアドレスを記録する関数の呼び出しと、前記スタックから前記レジスタの内容をリストアする命令(ldmfd sp!, {r0, r1, r2, r3})と、前記リターンレジスタに前記出口トレース関数の関数呼び出しを設定する命令(ldr lr, =__mv_functrace_exit)と、前記アドレスaddr3を前記プログラムカウンタに入れて前記関数に戻る命令(ldr pc, [sp, #0])を備える。
また同様に、前記出口トレース関数は以下の構成とする。つまり、前記関数終了時の最初の4つのレジスタの内容をスタックに保存せしめる命令(stmfd sp!, {r0, r1, r2, r3})と、前記関数の終了時刻とアドレスを記録する関数の呼び出しと、前記スタックから前記最初の4つのレジスタの内容をリストアする命令(ldmfd sp!, {r0, r1, r2, r3})と、前記スタックからアドレスaddr2を取得してプログラムカウンタに入れる命令(ldr pc, [sp, #-20])を備える。
モバイルシステムなどでは関数履歴のデータは、保存するバッファーがあまり膨大にならないようにサイクリックバッファーを用いれば少ないバッファー容量で関数履歴を効果的に記録・保存することができる。このバッファーに記録するデータが一杯になったら、古いデータから上書きしていく。なお、関数履歴のデータに含める関数のアドレスは、マップファイル等を用いて読みやすい関数の名前に変更することができる。
なお、上記のファンクショントレースに用いる入口トレース関数と出口トレース関数はダイナミックライブラリにて提供することができる。
なお、上記のファンクショントレース実装当たって、実装される関数が数十万個に及ぶ場合もあるため、既存のモバイルシステム用のソフトウェアを書き換えて本発明のリアルタイム診断システムを構築するためには手直し作業は数日間を必要とする膨大な手数がかかる。そこで、ファンクショントレース実装作業は自動化することが好ましい。
そこで、前記リアルタイム診断ソフトウェアの実装ツールを用意し、
前記アプリケーションおよび前記関数に対してオリジナルに準備されているそれぞれのビルドツールの名前を前記リアルタイム診断ソフトウェア実装ツールのコマンドの名前に変更するとともに、
前記リアルタイム診断ソフトウェア実装ツールのそれぞれのツールの名前を前記オリジナルのビルドツールの名前にそれぞれ変更し、
前記オリジナルのビルドツールの名前にてビルド実行コマンドを実行することにより、前記関数に前記ファンクショントレース用のリアルタイム診断ソフトウェアを自動的に実装せしめる。
上記構成により、ファンクショントレース実装作業は完全に自動化することができる。
前記アプリケーションおよび前記関数に対してオリジナルに準備されているそれぞれのビルドツールの名前を前記リアルタイム診断ソフトウェア実装ツールのコマンドの名前に変更するとともに、
前記リアルタイム診断ソフトウェア実装ツールのそれぞれのツールの名前を前記オリジナルのビルドツールの名前にそれぞれ変更し、
前記オリジナルのビルドツールの名前にてビルド実行コマンドを実行することにより、前記関数に前記ファンクショントレース用のリアルタイム診断ソフトウェアを自動的に実装せしめる。
上記構成により、ファンクショントレース実装作業は完全に自動化することができる。
本発明のリアルタイム診断システムではすべての関数にファンクショントレース手法を適用するのが基本であるが、関数の呼び出し関係に注目すれば、一部の関数については必ずしも個別にファンクショントレース手法を適用しなくても、以下のように関数呼び出し関係の上流および下流の関数に適用したファンクショントレースによって必要な関数履歴を得ることができる。
つまり、それぞれの前記関数をノードとし、それらの呼び出し関係をグラフ化したベクターグラフにおいて、ある上流ノードから下流ノードへのルートが一意に定まる場合、前記上流ノードおよび前記下流ノードに対しては前記ファンクショントレース用のリアルタイム診断ソフトウェアを実装せしめ、当該一意に定まるルート上にある中間ノードに対しては前記ファンクショントレースの実装を省略することができる。本発明ではこの実装省略手法をファンクショントレースに対するサンプリング実装手法と呼ぶ。
つまり、それぞれの前記関数をノードとし、それらの呼び出し関係をグラフ化したベクターグラフにおいて、ある上流ノードから下流ノードへのルートが一意に定まる場合、前記上流ノードおよび前記下流ノードに対しては前記ファンクショントレース用のリアルタイム診断ソフトウェアを実装せしめ、当該一意に定まるルート上にある中間ノードに対しては前記ファンクショントレースの実装を省略することができる。本発明ではこの実装省略手法をファンクショントレースに対するサンプリング実装手法と呼ぶ。
上記構成により、ファンクショントレースを入れなくても関数の呼び出しルートが分かる関数が選定され、ファンクショントレースを入れる関数を例えば全体の30%程度に抑えることができ、すべての関数にファンクショントレースを入れた時と比べてリアルタイムシステムに与えるオーバーヘッドを3分の1に削減することができる。
次に、本発明のリアルタイム診断システムは、上記のファンクショントレースを基本として、種々の応用を展開していくことができる。
第1の応用は、ロジカルエラーをトレースするもので、前記入口トレース関数が、前記関数の開始時刻と前記アドレスの記録に加えて前記関数の引数の値の記録を含む関数(入口ロジカルトレース関数)であり、前記出口トレース関数が、前記関数の終了時刻と前記アドレスの記録に加えて前記関数の返り値の記録を含む関数(出口ロジカルトレース関数)であり、前記関数の引数と返し値のトレースを実行するものである。
上記構成によれば、ロジカルエラーを診断するための関数の引数と返り値をトレースすることが可能である。
上記構成によれば、ロジカルエラーを診断するための関数の引数と返り値をトレースすることが可能である。
第2の応用は、メモリリークをトレースするもので、前記アプリケーションにおいてメモリの割り付けが関与するオペレーションが開始された場合に、前記オペレーション処理を前記関数呼び出しの処理と同様に扱い、前記入口トレース関数が、前記オペレーションの開始時刻と前記アドレスの記録に加えて前記オペレーション開始時における前記メモリの使用量の記録を含む関数(入口メモリトレース関数)であり、前記出口トレース関数が、前記オペレーションの終了時刻と前記アドレスの記録に加えて前記オペレーション終了時における前記メモリの使用量の記録を含む関数(出口メモリトレース関数)であり、前オペレーション開始時における前記メモリの使用量と前記オペレーション終了時における前記メモリの使用量の差分からメモリリークの検出を実行するものである。
上記構成により、アプリケーションのオペレーションの前後においてメモリ使用量を検知し、潜在的なメモリリークを検出することができる。
上記構成により、アプリケーションのオペレーションの前後においてメモリ使用量を検知し、潜在的なメモリリークを検出することができる。
第3の応用は、オペレーション処理の時間を計測するストップウォッチ機能を実現するもので、前記アプリケーションにおける処理時間の計測対象となるオペレーション処理を、前記関数呼び出しの処理と同様に扱い、前記入口トレース関数が、前記オペレーションの開始時刻と前記アドレスの記録を含む関数(入口オペレーショントレース関数)であり、前記出口トレース関数が、前記オペレーションの終了時刻と前記アドレスの記録を含む関数(出口オペレーショントレース関数)であり、前記オペレーションの前記開始時刻と前記終了時刻の差分から前記オペレーション処理にかかった時間を計測するストップウォッチ機能を実行するものである。
上記構成により、リアルタイムシステムにおける細かいオペレーションのパフォーマンスを測定することができ、測定した結果をレスポンスが遅い障害の診断に用いることができる。
上記構成により、リアルタイムシステムにおける細かいオペレーションのパフォーマンスを測定することができ、測定した結果をレスポンスが遅い障害の診断に用いることができる。
本発明によれば、コンパイルオプションを使用せずにリアルタイムソフトウェアシステムにリアルタイム性に影響しないファンクショントレースを実装することと、このファンクショントレースによってシステムに不具合が発生した時に不具合を診断するための必要な関数の呼び出し履歴データを漏れなく記録することができる。
本発明によれば、本発明におけるファンクショントレースは、アセンブリレベルで2つのアセンブリコードを各関数の冒頭に挿入して実行せしめることにより、従来のコンパイルオプションを用いる手法の8つ以上のアセンブリコードより元のシステムコードに追加するコードを4分の1で済むことができ、また例えば200MHzのプロセッサを搭載するシステムならば、従来のコンパイルオプションで実装したファンクショントレースに必要となる関数履歴のトレース時間20マイクロセカンドより、その10分の1である2マイクロセカンド以内で関数履歴のトレースを実行でき、システムのリアルタイム動作に影響しない水準でソフトウェア障害解析に重要なデータを取得することができる。
本発明によれば、ファンクショントレースによってシステムのフリーズ診断、ロジカルトレースによってシステムのロジカルエラー分析、メモリトレースによって潜在的なメモリリーク検出、ストップウォッチによってシステムの細かいパフォーマンス測定と遅いレスポンスの原因特定などの障害診断をシステムリソースが小さいワイヤレスデバイスなどであってもシステムのリアルタイム性への影響を最小化して実現することができる。
以下、本発明を実施するための最良の形態について実施例により具体的に説明する。本発明はこれらの実施例に限定されるものではない。なお、本発明はリアルタイムソフトウェアシステムのアプリケーションの中での実施例に限定されるものでなく、デバイスドライバとカネールから、ライブラリ、ミドウェアとアプリケーションまで実施することができる。
なお、以下の説明において、ワイヤレスデバイスは携帯電話に限定されることはないが、以下の説明では携帯電話を想定して説明する。
なお、以下の説明において、ワイヤレスデバイスは携帯電話に限定されることはないが、以下の説明では携帯電話を想定して説明する。
本発明のリアルタイム診断システムは、ファンクショントレースを基本とする。本発明におけるファンクショントレースとは、関数の呼び出し履歴(開始と終了時の時刻、関数のアドレス、引数と返し値)を記録することであり、ファンクショントレース手法の実現は、トレースされる関数へのリターンアドレスを一旦スタックに保存して関数の開始履歴(開始時の時刻、関数のアドレスと関数の引数)を記録するための入口トレース関数を呼び出しにかかる関数の先頭に挿入して、挿入した入口トレース関数の中で関数の終了履歴(終了時の時刻、関数のアドレス、関数の引数と返し値)を記録する出口トレース関数を呼び出してスタックに保存しているトレースされた関数へのリターンアドレスを取得して呼び出された場所へ戻られるようにすることにより実現する。
本発明におけるファンクショントレース手法は、コンパイルオプションを使用せず、アセンブリレベルで二つのアセンブリコード(ARM方式の場合に8バイト、THUMB方式の場合に4バイト)を各関数に挿入することにより実装できる。アセンブリコードの一方は、アプリケーションから関数を呼び出して関数実行後に戻るべきアドレスを設定するために用いられ、アセンブリコードの他方は、関数の開始履歴を記録する入口トレース関数の呼び出しに用いられる。
図1は、本発明のリアルタイム診断システムに適するファンクショントレースの実施形態を示した図であり、本発明のファンクショントレースを関数の呼び出しの流れに従って実施することを示している。一方、図2は、本発明のファンクショントレースの実施を自動化するツールの実装処理を示している。
図1に示すように、この例は、アプリケーション実行中に、関数user_func1をファンクションコールにより呼び出し、関数user_func1の実行後、アプリケーションに戻ってその実行を継続してゆく流れとなっている。この従来の流れではリアルタイムで障害診断に必要な関数履歴を得ることになっていない。
一方、図1(b)に示す本発明のリアルタイム診断システムでは、入口トレース関数(mv_functrace_enter)と、出口トレース関数(mv_functrace_exit)を備え、関数user_func1の冒頭部分に2つのアセンブリコード“str lr, [sp, #4]!”と“bl__mv_functrace_enter”が挿入されている。
一方、図1(b)に示す本発明のリアルタイム診断システムでは、入口トレース関数(mv_functrace_enter)と、出口トレース関数(mv_functrace_exit)を備え、関数user_func1の冒頭部分に2つのアセンブリコード“str lr, [sp, #4]!”と“bl__mv_functrace_enter”が挿入されている。
入口トレース関数(__mv_functrace_enter)とは、アプリケーションから関数(関数user_func1など)が呼び出しを受けた場合に関数の開始時刻とアドレスを含む関数履歴を記録する関数である。
出口トレース関数(__mv_functrace_exit)とは、関数(関数user_func1など)が終了する場合に関数の終了時刻とアドレスを含む関数履歴を記録する関数である。この出口トレース関数は、従来のコンパイルオプションを用いた手法のように直接にトレースされる関数に挿入されるのでなく、入口トレース関数の中でリターンレジスタを用いる仕組みによってトレースされる関数が終了する時に呼び出される。
関数user_func1の冒頭部分に加えられたアセンブリコードとは、アプリケーションから呼び出された際に関数の実行後に戻るべきアドレスをスタックに一時記憶するアセンブリ命令と、入口トレース関数を呼び出して実行するアセンブリ命令である。
出口トレース関数(__mv_functrace_exit)とは、関数(関数user_func1など)が終了する場合に関数の終了時刻とアドレスを含む関数履歴を記録する関数である。この出口トレース関数は、従来のコンパイルオプションを用いた手法のように直接にトレースされる関数に挿入されるのでなく、入口トレース関数の中でリターンレジスタを用いる仕組みによってトレースされる関数が終了する時に呼び出される。
関数user_func1の冒頭部分に加えられたアセンブリコードとは、アプリケーションから呼び出された際に関数の実行後に戻るべきアドレスをスタックに一時記憶するアセンブリ命令と、入口トレース関数を呼び出して実行するアセンブリ命令である。
以下、アプリケーションから関数user_func1を呼び出すアドレスをaddr1、関数user_func1の処理から戻るアドレスをaddr2、関数user_func1の最初の命令のアドレスをaddr3として処理の流れを追って説明する。
関数user_func1の冒頭に加える命令が、アドレスaddr2をスタックに一時記憶するアセンブリ命令と入口トレース関数を呼び出すアセンブリ命令となっており、アプリケーションから関数user_func1が呼び出されると、関数user_func1の開始時に入口トレース関数を呼び出して関数履歴を取得し、関数user_func1に戻って関数user_func1本体の内容を実行し、関数user_func1の終了時に出口トレース関数を呼び出して関数履歴を取得した後、スタックに一時記憶したアドレスaddr2を手掛かりとしてアプリケーションに戻ることにより、関数履歴のトレース(ファンクショントレース)を実行する。
前者のアセンブリコード“str lr, [sp, #4]!”は、ファンクショントレース関数を実行してから元の場所に戻るために関数user_func1が呼び出された直後のアドレスaddr2を一旦スタックに保存する命令となっている。このスタックにアドレスaddr2を一時保存しておく仕組みは本発明における重要な手法の一つであり、後述するように、出口トレース関数の終了時点にスタックから読み出してプログラムカウンタに書き込むことによりアプリケーションのアドレスaddr2に戻ることが可能となる。
後者のアセンブリコード“bl __mv_functrace_enter”は、関数user_func1から入口トレース関数“__mv_functrace_enter”を呼び出すアセンブリ命令である。
後者のアセンブリコード“bl __mv_functrace_enter”は、関数user_func1から入口トレース関数“__mv_functrace_enter”を呼び出すアセンブリ命令である。
入口トレース関数“__mv_functrace_enter”では、まずリターンレジスタLRにある挿入した二つのアセンブリの直後になるアドレスaddr3をスタックに保存する。そして、引数が入っている最初の4つのレジスタR0、R1、R2とR3を一時スタックに保存してから関数の入口(関数開始時点)で履歴を記録する作業を行う。保存されたレジスタR0、R1、R2とR3をスタックから戻して、リターンレジスタLRに関数の出口で履歴を記録するための出口トレース関数“__mv_functrace_exit”のアドレスを設定する。最後にスタックに保存されたアドレスaddr3をレジスタPCに入れて、トレースされる関数の最初の命令へ実行を移行する。関数の実行が終るとリターンレジスタLRに出口トレース関数へのアドレスが入っているために実行はこの出口トレース関数へ移行する。このリターンレジスタLRを用いて出口トレース関数を呼び出す仕組みは、本発明における重要な手法のもう一つである。
ファンクショントレースの動作を鳥瞰すると次のステップになる。
(1)アプリケーションから関数user_func1を呼び出する命令“bl user_func1”を実行して関数user_func1へ飛び、挿入した二つの命令の一つ目である“str lr, [sp, #4]!”を実行する。
(2)挿入した二つ目の命令である“bl __mv_functrace_enter”を実行してファンクション関数__mv_functrace_enterへ飛び、関数の入口(開始時点)で関数を呼び出す時刻と関数user_func1のアドレスを関数履歴として記録する。
(3)関数user_func1に戻るためのアドレスaddr3をレジスタPCに設定したので、user_func1の最初の命令へ実行を移行し、関数user_func1の元のコードをすべて実行する。
(4)入口トレース関数__mv_functrace_enterの処理中でレジストLRに出口トレース関数mv_functrace_exitのアドレスを設定しているために、関数user_func1の実行が終った後に当該リターンレジスタに設定されている出口トレース関数のアドレスをプログラムカウンタに入れ、関数__mv_functrace_exitへ実行を移行し、関数の出口(終了時点)での履歴となる関数を終了する時刻と関数のアドレスを記録する。
(5)__mv_functrace_exitの最後に、スタックに保存している元のアプリケーションへ戻るためのアドレスaddr2をレジスタPCに入れ、user_func1を呼び出した直後の命令へ実行を移行する。
つまり、アプリケーションのアドレスaddr1から関数の呼び出し実行、関数の開始時に入口トレース関数の実行、アドレスaddr3に戻って関数の実行、関数の終了時に出口トレース関数の実行を経て、アプリケーションのアドレスaddr2に戻ることによりファンクショントレースを実行するものとなっている。
なお、ファンクショントレース関数“__mv_functrace_enter”と“__mv_functrace_exit”は、ダイナミックライブラリで提供される。
上記構成によれば、ファンクショントレース関数はその実行時間が例えば200MHzのプロセッサを搭載するシステム上では2マイクロセカンド以内となり、システム全体の動作に影響しない水準とすることができる。
上記構成によれば、ファンクショントレース関数はその実行時間が例えば200MHzのプロセッサを搭載するシステム上では2マイクロセカンド以内となり、システム全体の動作に影響しない水準とすることができる。
次に、上記のファンクショントレースの自動的実装について述べる。
上記ファンクショントレースの実装を自動化することは重要である。モバイルシステムのような比較的規模の小さいシステムであっても実装される関数は数十万個となることが想定され、ビルド用makefileの数も数百から数千になることが想定される。数多くのmakefileを手作業で行なうと数日間を要することとなる。そこで実装作業を自動化する必要がある。
上記ファンクショントレースの実装を自動化することは重要である。モバイルシステムのような比較的規模の小さいシステムであっても実装される関数は数十万個となることが想定され、ビルド用makefileの数も数百から数千になることが想定される。数多くのmakefileを手作業で行なうと数日間を要することとなる。そこで実装作業を自動化する必要がある。
本発明におけるファンクショントレースを自動的に実装する手法を図2に示す。手作業による実装に代え、ファンクショントレースを実装するためのツールを用意し、この実装ツールはすべての元のビルドコマンドラインを吸収してファンクショントレースに必要な作業を行い、最後に元のビルド作業を継続させる。
この実装手法は次のステップになる。
(1)元のビルドツールであるarm-linux-gcc、arm-linux-g++、arm-linux-ld、arm-linux-arの名前をmv-arm-linux-gcc、mv-arm-linux-g++、mv-arm-linux-ld、mv-arm-linux-arにそれぞれ変更する。
(2)ファンクショントレースの実装ツールであるmv_make_gcc、mv_make_g++、mv_make_ld、mv_make_arの名前を元のビルドツールarm-linux-gcc、arm-linux-g++、arm-linux-ldにそれぞれ変更する。
(3)ファンクショントレース実装に必要な設定ファイルmv_make.cfgを指定する環境変数MV_MAKE_CFGに設定する。
(4)従来通りターゲットをビルドするためのコマンド、例えばmake buildを実行してすべての必要な関数にファンクショントレースを自動的に実装する。
上記のように、ファンクショントレースを実装する際には、ファンクショントレース実装ツールが元のビルドツールの名前になっているので、まず従来通りに実行したビルドコマンドをファンクショントレース実装ツールに渡して以下のように分析を行い、ファンクショントレースを実装する。
コマンドラインにあるファイルに関してファンクショントレースが必要でない場合はコマンドを直接にGNUツールに渡す。
コマンドラインにあるファイルに関してファンクショントレースが必要でない場合はコマンドを直接にGNUツールに渡す。
ファンクショントレースが必要である場合はコマンドの違いにより次のようにケース分類する。
もしコマンドがarである場合には、オブジェクトにファンクショントレースが既に挿入されていれば、weakで設定したファンクショントレース関数を入れたダミーのオブジェクトを作り、GUNのar (mv-arm-linux-ar)を実行する。
もしコマンドがldである場合にはオブジェクトにファンクショントレースが既に挿入されていればファンクショントレース用ライブラリをコマンドラインにリンクオプションを追加してGNU ld (mv-arm-linux-ld)を実行する。
もし、コマンドがgxxである場合にはGNU gxx (mv-arm-linux-gxx)によってソースコードのアセンブリを生成して必要に応じて関数にファンクショントレース用の二つのアセンブリを挿入し、コマンドラインに元のソースファイルを生成したアセンブリファイルに変更してアセンブリをコンパイルする新しいコマンドラインをGNU gxxに渡して実行する。
すべてのプロジェクトビルドが完了するまで以上の作業を繰り返す。最後にファンクショントレース実装ログを記録する。
上記実装手法によればファンクショントレース実装作業は完全に自動化することができる。
上記実装手法によればファンクショントレース実装作業は完全に自動化することができる。
本発明のリアルタイム診断システムではすべての関数にファンクショントレース手法を適用するのが基本であるが、関数の呼び出し関係に注目すれば、一部の関数については必ずしも個別にファンクショントレースを適用しなくても、関数呼び出し関係の上流および下流の関数に適用したファンクショントレースから必要な関数履歴を得ることができる。
実施例2はファンクショントレースに対する実装省略手法を説明する。ここではサンプリング実装手法と呼ぶ。
実施例2はファンクショントレースに対する実装省略手法を説明する。ここではサンプリング実装手法と呼ぶ。
サンプリング実装手法では、それぞれの関数をノードとし、それらの呼び出し関係をグラフ化したベクターグラフにおいて、ある上流ノードから下流ノードへのルートが一意に定まる場合、上流ノードおよび下流ノードに対してはファンクショントレースを実装し、当該一意に定まるルート上にある中間ノードに対してはファンクショントレース実装を省略するものである。
中間ノードではファンクショントレースを入れなくても関数の呼び出しルートが分かるので省略しても良く、ファンクショントレースを挿入する関数を例えば全体の30%程度に抑えることができる。
中間ノードではファンクショントレースを入れなくても関数の呼び出しルートが分かるので省略しても良く、ファンクショントレースを挿入する関数を例えば全体の30%程度に抑えることができる。
図3は、関数の呼び出し関係を示すベクターグラフとサンプリングアルゴリズムによりファンクショントレースの実装が省略されうる中間ノードの選択の原理を説明する図である。
[セットアップ]
GSをベクターグラフの集合とし、その中にあるグラフがバイナリファイルと対応するものとする。GはGSの中にあるエレメント即ち一つのベクターグラフとする。uは、サンプリング実施関数SAMPLING_VERTEXのパラメータであり、ベクターグラフの中にあるノードである。各ノードであるuには、以下のパラメータが有する。
GSをベクターグラフの集合とし、その中にあるグラフがバイナリファイルと対応するものとする。GはGSの中にあるエレメント即ち一つのベクターグラフとする。uは、サンプリング実施関数SAMPLING_VERTEXのパラメータであり、ベクターグラフの中にあるノードである。各ノードであるuには、以下のパラメータが有する。
color[u]
color[u]はノードのカラーを表し、GRAYで初期化される。カラーの値は3種類がある。GRAYは、アルゴリズムによってベクターグラフの全体を処理(traverse)する中で通っていなくfunctraceを入れるかどうまた分からない状態を表す。WHITEは通ったノードにfunctraceが必要としないことを表す。BLACKはノードを通りかけ、functraceが必要とする処理を済んだことを表す。
color[u]はノードのカラーを表し、GRAYで初期化される。カラーの値は3種類がある。GRAYは、アルゴリズムによってベクターグラフの全体を処理(traverse)する中で通っていなくfunctraceを入れるかどうまた分からない状態を表す。WHITEは通ったノードにfunctraceが必要としないことを表す。BLACKはノードを通りかけ、functraceが必要とする処理を済んだことを表す。
name[u]
name[u]は、ベクターグラフにノードを表し、例えばname[1]="1" name[2]="2"がノード“1”と“2”を表現する。
name[u]は、ベクターグラフにノードを表し、例えばname[1]="1" name[2]="2"がノード“1”と“2”を表現する。
gap[u]
gap[u]は、あるノードとそのノードに属するすべての子供ノードにfunctraceが必要としない集合を現す。
gap[u]は、あるノードとそのノードに属するすべての子供ノードにfunctraceが必要としない集合を現す。
sons[u]
sons[u]はノードのすべての子供ノードを表す。例えば、図3には次の子供集合、sons[5]={7,8,10,11,12},sons[4]={6,9,10}がある。
sons[u]はノードのすべての子供ノードを表す。例えば、図3には次の子供集合、sons[5]={7,8,10,11,12},sons[4]={6,9,10}がある。
extern[u]
extern[u]は、ベクターグラフ間の関数呼び出しを表し、次の二つの値TRUEとFALSEを有する。
TRUE:あるノードからベクターグラフ外の関数を呼び出している。例えば図3にあるノード3はそのノードである。
FALSE :ノードから外部関数を呼び出していない。
extern[u]は、ベクターグラフ間の関数呼び出しを表し、次の二つの値TRUEとFALSEを有する。
TRUE:あるノードからベクターグラフ外の関数を呼び出している。例えば図3にあるノード3はそのノードである。
FALSE :ノードから外部関数を呼び出していない。
extern_invoked[u]
extern_invoked[u]は外部関数から呼び出されていることを表し、次の二つの値TRUEとFALSEを有する。
TRUE:外部から呼び出されている。例えば図3にあるノード14はそのノードである。
FALSE:外部からよびだされていない。
extern_invoked[u]は外部関数から呼び出されていることを表し、次の二つの値TRUEとFALSEを有する。
TRUE:外部から呼び出されている。例えば図3にあるノード14はそのノードである。
FALSE:外部からよびだされていない。
is_top[u]
is_top[u]は、誰にも呼び出されないノードを表し、例えば、図3にあるノード“13”“1”“2”がこの種類のノードであり、次の二つの値TRUEとFALSEを有する。
TRUE:このノードがベクターグラフの中で誰にも呼び出されていない。
FALSE:このノードが少なくとも一つの関数に呼び出されている。
is_top[u]は、誰にも呼び出されないノードを表し、例えば、図3にあるノード“13”“1”“2”がこの種類のノードであり、次の二つの値TRUEとFALSEを有する。
TRUE:このノードがベクターグラフの中で誰にも呼び出されていない。
FALSE:このノードが少なくとも一つの関数に呼び出されている。
図4にSAMPLING_VERTEX(u)のアルゴリズムの例を示す。
以下に、図4に示したSAMPLING_VERTEX(u)のアルゴリズムの実行例を示す。
以下に、図4に示したSAMPLING_VERTEX(u)のアルゴリズムの実行例を示す。
MAX_FUNCTRACE_GAPを2に設定する。
次の状況から
is_top[1]=TRUE, is_top[2]=TRUE, is_top[13]=TRUE
extern[3]=TRUE
extern_invoked[14]=TRUE
次の状況から
is_top[1]=TRUE, is_top[2]=TRUE, is_top[13]=TRUE
extern[3]=TRUE
extern_invoked[14]=TRUE
ノード1,2,3,13,14はfunctraceを入れることになる。すべての集合は次のようになる。
Gap[16]={}
Gap[17]={}
Gap[15]={16, 17} functraceを入れる。
Gap[9]={}
Gap[10]={}
Gap[6]={9,10} functraceを入れる。
Gap[7]={10} functraceを入れる。
Gap[11]={}
Gap[12]={}
Gap[8]={11,12} functraceを入れる。
Gap[4]={} 注意:ノードの子供ノード6にfunctraceを入れたためにGap[6]はGap[4]に合併しない。
Gap[5]={} 同上
Gap[2]={4,5} functraceを入れる。
Gap[16]={}
Gap[17]={}
Gap[15]={16, 17} functraceを入れる。
Gap[9]={}
Gap[10]={}
Gap[6]={9,10} functraceを入れる。
Gap[7]={10} functraceを入れる。
Gap[11]={}
Gap[12]={}
Gap[8]={11,12} functraceを入れる。
Gap[4]={} 注意:ノードの子供ノード6にfunctraceを入れたためにGap[6]はGap[4]に合併しない。
Gap[5]={} 同上
Gap[2]={4,5} functraceを入れる。
図5は上記のアルゴリズムの実行結果を示す図である。
図5に示すように、黒く塗られたノードはファンクショントレースが実装され、白く塗られたノードはファンクショントレースの実装が省略される。ノード間にスキップする数であるMAX_FUNCTRACE_GAPを2に設定した場合にfunctraceの数が半分に減らすことができた。
図5に示すように、黒く塗られたノードはファンクショントレースが実装され、白く塗られたノードはファンクショントレースの実装が省略される。ノード間にスキップする数であるMAX_FUNCTRACE_GAPを2に設定した場合にfunctraceの数が半分に減らすことができた。
もしこのMAX_FUNCTRACE_GAPを4に設定するとファンクショントレースを実装するノードの数をさらに減らすことができる。
上流と下流のノードの間に数個のノードをスキップしても、関数の呼び出しルートを分かる。例えば、ノード2とノード6の間にノード4にファンクショントレースを挿入していないが、関数の呼び出しルートはノード2、4、6であることを間違いなく再現することができる。
上流と下流のノードの間に数個のノードをスキップしても、関数の呼び出しルートを分かる。例えば、ノード2とノード6の間にノード4にファンクショントレースを挿入していないが、関数の呼び出しルートはノード2、4、6であることを間違いなく再現することができる。
本発明のリアルタイム診断システムは、実施例1で説明したファンクショントレース手法を基本として、種々の応用が可能である。
実施例3では第1の応用として、ロジカルエラーをトレースするものを説明する。
実施例3では第1の応用として、ロジカルエラーをトレースするものを説明する。
実施例3のリアルタイム診断システムでは、ファンクショントレース手法を用いて、ファンクショントレース関数の中で呼び出された関数の引数を関数の入口(関数開始時点)で記録し、返し値を出口(関数終了時点)で記録する。この関数の引数と返し値は、関数の呼び出し履歴を一緒に記録するが、記録データを保存するバッファーが膨大に要求されないように最初の4つの引数のみ(20バイト分)を記録する。リアルタイムシステムには、4つの引数を持つ関数が全体の90%を占めるので効率的なものとすることができる。また、最初の4つの引数は、実施例1に示したようにレジスタにあるためにファンクショントレース実行の過程で同時に記録することができ、余分のオーバーヘッドが発生しない。
図6は実施例3のロジカルエラーを診断するためのロジトレース手法を実施した例を示した図である。
関数の引数と返し値トレースは次のステップになる。
関数の引数と返し値トレースは次のステップになる。
(1)アプリケーションの中で関数func_1を呼び出してfunc_1へ移行する。
(2)functrace手法によってfunc_1の先頭にファンクショントレースの入口トレース関数mv_ft_enterを挿入してあるために、実行はこのmv_ft_enterへ移行する。
(3)関数mv_ft_enterの中では、ファンクショントレースのデータ(関数の呼び出し時刻と関数のアドレス)とR0からR3までのレジスタにある関数の引数を保存する。
(4)そして、実行はmv_ft_enterを呼び出したfunc_1へ戻る。
(5)func_1の中で元のfunc_1のコードを実行してから出口トレース関数mv_ft_exitへ実行を移行する。
(6)mv_ft_exitの中では、レジスタR0にある関数func_1の返し値を記録する。
(7)関数func_1の呼び出された場所の後に実行を移行する。
すべての関数の引数と返し値は、ファンクショントレースと共に(1)から(7)までの作業を繰り返して記録される。また、記録場所もファンクショントレースと同じバッファーである。
(2)functrace手法によってfunc_1の先頭にファンクショントレースの入口トレース関数mv_ft_enterを挿入してあるために、実行はこのmv_ft_enterへ移行する。
(3)関数mv_ft_enterの中では、ファンクショントレースのデータ(関数の呼び出し時刻と関数のアドレス)とR0からR3までのレジスタにある関数の引数を保存する。
(4)そして、実行はmv_ft_enterを呼び出したfunc_1へ戻る。
(5)func_1の中で元のfunc_1のコードを実行してから出口トレース関数mv_ft_exitへ実行を移行する。
(6)mv_ft_exitの中では、レジスタR0にある関数func_1の返し値を記録する。
(7)関数func_1の呼び出された場所の後に実行を移行する。
すべての関数の引数と返し値は、ファンクショントレースと共に(1)から(7)までの作業を繰り返して記録される。また、記録場所もファンクショントレースと同じバッファーである。
上記のように、実施例1で示したファンクショントレース手法をベースとしながら入口(関数開始時)における4つの引数のトレースと、出口(関数終了時)における返り値のトレースを実行する。
実施例4では第2の応用として、メモリリークをトレースするものを説明する。
アプリケーションにおいてメモリの割り付けが関与するオペレーションが開始された場合に、オペレーション処理を関数呼び出しの処理と同様に扱い、ファンクショントレースの手法を応用しつつ、潜在的なメモリリークを検出する。
アプリケーションにおいてメモリの割り付けが関与するオペレーションが開始された場合に、オペレーション処理を関数呼び出しの処理と同様に扱い、ファンクショントレースの手法を応用しつつ、潜在的なメモリリークを検出する。
本手法は、潜在的なメモリリークが、繰り返し動作の中で割り付けられたメモリの開放漏れによって発生するものであると推定し、すべての操作の入口関数にファンクショントレース手法を用いて入口メモリトレース関数および出口メモリトレース関数を挿入して動作前と動作後のメモリ使用量を取得してその差を求め、同じ動作が繰り返された時にこの差が直線的に増加するのであれば、メモリがこの動作の中で漏れたことと断定し、漏れた場所と具体的な漏れたメモリの量を特定する。
入口メモリトレース関数は、オペレーションの開始時刻とアドレスの記録に加えてオペレーション開始時におけるメモリの使用量の記録を含む関数であり、出口トレース関数は、オペレーションの終了時刻とアドレスの記録に加えてオペレーション終了時におけるメモリの使用量の記録を含む関数であり、オペレーション開始時におけるメモリの使用量とオペレーション終了時におけるメモリの使用量の差分からメモリリークの検出を実行する。
図7は実施例4の潜在的なメモリリークを検出するためのメモリトレース手法を実施した例を示した図である。
(1)アプリケーションの中である操作に関連する関数、例えばOperation_1を呼び出した時に実行をその関数へ移行する。
(2)Operation_1関数の中では、最初にメモリトレース関数mv_mm_enterを呼び出す。
(3)mv_mm_enterでは、その時点(動作が始まる前)でのメモリ使用量を取得してメモリトレースデータとしてバッファーに保存する。
(4)mv_mm_enterを呼び出したOperation_1関数のコードへ実行を移行し、Operation_1関数にあるすべての元のコードを実行し、動作をすべて完了させる。
(5)Operation_1関数のExitでファンクショントレース手法によって設定されたメモリトレース関数mv_mm_exitへ実行を移行する。
(6)mv_mm_exitでは、Operation_1関数の出口(関数終了時点)で呼び出されるために動作のすべてが完了してあり、この時点でメモリ使用量を取得する。
(7)Operation_1関数が呼び出された場所の直後に戻る。
よって、特定な動作で漏れたメモリは、Operation_1関数の入口で取得したメモリ使用量と出口で取得したメモリ使用量の差を求めることによって検出される。
(2)Operation_1関数の中では、最初にメモリトレース関数mv_mm_enterを呼び出す。
(3)mv_mm_enterでは、その時点(動作が始まる前)でのメモリ使用量を取得してメモリトレースデータとしてバッファーに保存する。
(4)mv_mm_enterを呼び出したOperation_1関数のコードへ実行を移行し、Operation_1関数にあるすべての元のコードを実行し、動作をすべて完了させる。
(5)Operation_1関数のExitでファンクショントレース手法によって設定されたメモリトレース関数mv_mm_exitへ実行を移行する。
(6)mv_mm_exitでは、Operation_1関数の出口(関数終了時点)で呼び出されるために動作のすべてが完了してあり、この時点でメモリ使用量を取得する。
(7)Operation_1関数が呼び出された場所の直後に戻る。
よって、特定な動作で漏れたメモリは、Operation_1関数の入口で取得したメモリ使用量と出口で取得したメモリ使用量の差を求めることによって検出される。
この手法は、潜在的なメモリ漏れを検出するために対象となるすべての動作の入口関数リストをファームウェアをビルドする前に予めに用意する必要がある。記録場所はファンクショントレースと分けた別のバッファーである。
なお上記実装では、関数呼び出しの入口と出口の2箇所においてメモリ使用量を取得して差分を得る方法であったが、2回分の操作をまとめて差分を算出することでもメモリリークを検出することは可能である。Operation_1関数の入口で1回取得して、次回のOperation_1関数の出口で1回取得しておき、2回の動作間におけるメモリ使用量の差を求めることによって漏れたメモリを検出することも機能的には可能であり、メモリ使用量の取得回数が少なくて済むので負荷を低減させることができる。
上記構成により、アプリケーションのオペレーションの前後においてメモリ使用量を検知し、潜在的なメモリリークを検出することができる。
実施例5では第3の応用として、アプリケーションの処理時間を正確に計測することができるストップウォッチ機能を説明する。
アプリケーションにおける処理時間の計測対象となるオペレーション処理を、関数呼び出しの処理と同様に扱ってタイムスタンプを取り、関数開始時刻と終了時刻の差から処理時間を求めるものである。
アプリケーションにおける処理時間の計測対象となるオペレーション処理を、関数呼び出しの処理と同様に扱ってタイムスタンプを取り、関数開始時刻と終了時刻の差から処理時間を求めるものである。
本発明における処理ごとのパフォーマンス測定ストップウォッチ手法は、リアルタイムシステムにおいて、あらゆるオペレーションで実際にかかった時間をファンクショントレースのタイムスタンプデータによって表示する(例えばマイクロセカンド単位で表示する)ものであり、遅いレスポンスに対してどこで遅くなったかを関数レベルで示すことができる。
本手法は、ファンクショントレース手法を用いてパフォーマンスを測定する対象となるオペレーションの入口関数にファンクショントレース関数をストップウォッチとして入れ、実行した際にその関数開始時刻のタイムスタンプとその関数終了時刻のタイムスタンプを取得することによりオペレーションの時間を測定するストップウォッチを実現する。
本手法は、ファンクショントレース手法を用いてパフォーマンスを測定する対象となるオペレーションの入口関数にファンクショントレース関数をストップウォッチとして入れ、実行した際にその関数開始時刻のタイムスタンプとその関数終了時刻のタイムスタンプを取得することによりオペレーションの時間を測定するストップウォッチを実現する。
このストップウォッチ手法は、図8に示しているように次のステップによってリアルタイムシステムにおける細かいオペレーションのパフォーマンスを測定し、測定した結果を分析するためのデータを提供する。
図8は実施例5のストップウォッチ手法を実施した例を示した図である。
図8は実施例5のストップウォッチ手法を実施した例を示した図である。
(1)アプリケーションの中である操作の入口関数例えばOperation_1を呼び出した時に実行をその関数へ移行する。
(2)Operation_1関数の中では、最初にファンクショントレース関数mv_ft_enterを呼び出す。
(3)mv_ft_enterでは、その時点(動作が始まる直前)でのタイムスタンプを取得してバッファーに記録する。
(4)mv_ft_enterを呼び出したOperation_1関数のコードへ実行を移行し、Operation_1関数にあるすべての元のコードを実行し、動作をすべて完了させる。
(5)Operation_1関数の出口でファンクショントレース手法によって設定されたファンクショントレース関数mv_ft_exitへ実行を移行する。
(6)mv_ft_exitでは、Operation_1関数の出口(終了直前)で呼び出されるために動作のすべてが完了してあり、この時点でのタイムスタンプを取得してバッファーに記録する。
(7)Operation_1関数が呼び出された場所の直後に戻る。
計測が必要な操作に関するストップウォッチ機能は、ファンクショントレースと共に(1)から(7)までの作業を繰り返して記録される。また、記録場所もファンクショントレースと同じバッファーである。
(2)Operation_1関数の中では、最初にファンクショントレース関数mv_ft_enterを呼び出す。
(3)mv_ft_enterでは、その時点(動作が始まる直前)でのタイムスタンプを取得してバッファーに記録する。
(4)mv_ft_enterを呼び出したOperation_1関数のコードへ実行を移行し、Operation_1関数にあるすべての元のコードを実行し、動作をすべて完了させる。
(5)Operation_1関数の出口でファンクショントレース手法によって設定されたファンクショントレース関数mv_ft_exitへ実行を移行する。
(6)mv_ft_exitでは、Operation_1関数の出口(終了直前)で呼び出されるために動作のすべてが完了してあり、この時点でのタイムスタンプを取得してバッファーに記録する。
(7)Operation_1関数が呼び出された場所の直後に戻る。
計測が必要な操作に関するストップウォッチ機能は、ファンクショントレースと共に(1)から(7)までの作業を繰り返して記録される。また、記録場所もファンクショントレースと同じバッファーである。
なお、上記ストップウォッチ手法を実現するには、前提として、ファームウェアをビルドする前にパフォーマンスを測定する対象となるすべてのオペレーションの入口関数リストをメーカ側から予め提供してもらう必要がある。
上記構成により、リアルタイムシステムにおける細かいオペレーションのパフォーマンスを測定することができ、測定した結果を障害の診断に用いることができる。
上記構成により、リアルタイムシステムにおける細かいオペレーションのパフォーマンスを測定することができ、測定した結果を障害の診断に用いることができる。
以上、本発明のリアルタイム診断システムの好ましい実施形態を図示して説明してきたが、本発明の技術的範囲を逸脱することなく種々の変更が可能であることは理解されるであろう。
本発明は、携帯電話などのワイヤレスデバイス、キャリア用の各種の組込み型サーバ、ルータなどの各種ネットワークデバイス、カーナビデバイス、ゲーム端末、テレビなどのセットボックス、インテリジェント家電製品、ロボット、工作機械装置など多様なシステムに広く適用することができる。
Claims (12)
- アプリケーション(オペレーティングシステムやデバイスドライバなどを含むあらゆるプログラムを意味する)と関数を備えたリアルタイムソフトウェアシステムに対して、
前記アプリケーションから前記関数が呼び出しを受けた場合に前記関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、前記関数が終了する場合に前記関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数とを備え、
それぞれの前記関数の冒頭に、前記アプリケーションから呼び出された際に前記関数の実行後に戻るべきアドレスをスタックに一時記憶する命令と、前記入口トレース関数を呼び出して実行する命令を加え、
前記アプリケーションから前記関数が呼び出されると、前記関数の開始時に前記入口トレース関数を呼び出して前記関数履歴を取得し、前記関数に戻って前記関数本体の内容を実行し、前記関数の終了時に前記出口トレース関数を呼び出して前記関数履歴を取得しその関数履歴となるトレースデータをサイクリックバッファーに保存した後、前記スタックに一時記憶した前記アドレスを手掛かりとして前記アプリケーションに戻ることにより、前記関数履歴のトレース(ファンクショントレース)を実行することを特徴とする利用者システムのリアルタイム診断システム。 - 前記アプリケーションから前記関数を呼び出すアドレスをaddr1、前記関数処理から戻るアドレスをaddr2、前記関数の最初の命令のアドレスをaddr3とし、
前記関数の冒頭に加える命令が、前記アドレスaddr2をスタックに一時記憶するアセンブリ命令と前記入口トレース関数を呼び出すアセンブリ命令であり、
前記入口トレース関数が前記関数開始履歴の取得後に、リターンレジスタに前記出口トレース関数の呼び出しを設定する命令と、前記関数のアドレスaddr3に戻る命令とを備え、
前記関数が最後に前記リターンレジスタに設定されている前記出口トレース関数をプログラムカウンタに入れる命令を備え、
前記出口トレース関数が前記関数終了履歴の取得後に、前記スタックに一時記憶されている前記アドレスaddr2をプログラムカウンタに入れる命令を備え、
前記アプリケーションの前記アドレスaddr1から前記関数の呼び出し実行、前記関数の開始時に前記入口トレース関数の実行、前記アドレスaddr3に戻って前記関数の実行、前記関数の終了時に前記出口トレース関数の実行を経て、前記アプリケーションのアドレスaddr2に戻ることにより前記ファンクショントレースを実行することを特徴とする、請求項1に記載のリアルタイム診断システム。 - 前記入口トレース関数が、リターンレジスタにある前記アドレスaddr3をスタックに保存せしめる命令と、前記関数開始時のレジスタの内容をスタックに保存せしめる命令と、前記関数の開始時刻とアドレスを記録する命令と、前記スタックから前記レジスタの内容をリストアする命令と、前記リターンレジスタに前記出口トレース関数の関数呼び出しを設定する命令と、前記アドレスaddr3を前記プログラムカウンタに入れて前記関数に戻る命令を備え、
前記出口トレース関数が、前記関数終了時のレジスタ(R0からR3まで)の内容をスタックに保存せしめる命令と、前記関数の終了時刻とアドレスを記録する命令と、前記スタックから前記レジスタの内容をリストアする命令と、前記スタックからアドレスaddr2を取得してプログラムカウンタに入れる命令を備えたことを特徴とする請求項2に記載のリアルタイム診断システム。 - 前記入口トレース関数の、前記関数開始時のレジスタの内容のスタック保存命令が、引数が入っている最初の4つのレジスタ(R0からR3まで)のデータを一時的にスタックに保存する命令であり、
前記出口トレース関数の、前記関数終了時のレジスタの内容のスタック保存命令が、前記関数のリターン値が入っているR0を含める最初の4つのレジスタ(R0からR3まで)のデータを一時的にスタックに保存する命令である請求項3に記載のリアルタイム診断システム。 - 前記入口トレース関数と、前記出口トレース関数を、ダイナミックライブラリにて提供する請求項1から4のいずれかに記載のリアルタイム診断システム。
- それぞれの前記関数に対する前記ファンクショントレース用のリアルタイム診断ソフトウェアの実装にあたり、
前記リアルタイム診断ソフトウェアの実装ツールを用意し、
前記アプリケーションおよび前記関数に対してオリジナルに準備されているそれぞれのビルドツールの名前を前記リアルタイム診断ソフトウェア実装ツールのコマンドの名前に変更するとともに、
前記リアルタイム診断ソフトウェア実装ツールのそれぞれのツールの名前を前記オリジナルのビルドツールの名前にそれぞれ変更し、
前記オリジナルのビルドツールの名前にてビルド実行コマンドを実行することにより、前記関数に前記ファンクショントレース用のリアルタイム診断ソフトウェアを自動的に実装せしめたことを特徴とする請求項1から5のいずれかに記載のリアルタイム診断システム。 - それぞれの前記関数をノードとし、それらの呼び出し関係をグラフ化したベクターグラフにおいて、
ある上流ノードから下流ノードへのルートが一意に定まる場合、前記上流ノードおよび前記下流ノードに対しては前記ファンクショントレース用のリアルタイム診断ソフトウェアを実装せしめ、当該一意に定まるルート上にある2つ以上の中間ノードに対しては前記ファンクショントレース用の入口トレース関数と出口トレース関数の実装を省略する請求項6に記載のリアルタイム診断システム。 - 前記入口トレース関数が、前記関数の開始時刻と前記アドレスの記録に加えて前記関数の引数の値の記録を含む関数(入口ロジカルトレース関数)であり、
前記出口トレース関数が、前記関数の終了時刻と前記アドレスの記録に加えて前記関数の返り値の記録を含む関数(出口ロジカルトレース関数)であり、
前記関数の引数と返し値のトレースを実行する請求項1から7のいずれかに記載のリアルタイム診断システム。 - 前記アプリケーションにおいてメモリの割り付けが関与するオペレーションが開始された場合に、前記オペレーション処理を前記関数呼び出しの処理と同様に扱い、
前記入口トレース関数が、前記オペレーションの開始時刻と前記アドレスの記録に加えて前記オペレーション開始時における前記メモリの使用量の記録を含む関数(入口メモリトレース関数)であり、
前記出口トレース関数が、前記オペレーションの終了時刻と前記アドレスの記録に加えて前記オペレーション終了時における前記メモリの使用量の記録を含む関数(出口メモリトレース関数)であり、
前オペレーション開始時における前記メモリの使用量と前記オペレーション終了時における前記メモリの使用量の差分からメモリリークの検出を実行する請求項1から7のいずれかに記載のリアルタイム診断システム。 - 前記アプリケーションにおける処理時間の計測対象となるオペレーション処理を、前記関数呼び出しの処理と同様に扱い、
前記入口トレース関数が、前記オペレーションの開始時刻と前記アドレスの記録を含む関数(入口オペレーショントレース関数)であり、
前記出口トレース関数が、前記オペレーションの終了時刻と前記アドレスの記録を含む関数(出口オペレーショントレース関数)であり、
前記オペレーションの前記開始時刻と前記終了時刻の差分から前記オペレーション処理にかかった時間を計測するストップウォッチ機能を実行する請求項1から7のいずれかに記載のリアルタイム診断システム。 - 前記リアルタイムソフトウェアシステムがワイヤレスモバイルシステム、組み込み型のキャリアサーバシステムまたはネットワークデバイスのいずれかである請求項1から10のいずれかに記載のリアルタイム診断システム。
- アプリケーションと関数を備えたリアルタイムソフトウェアシステムに対して、
前記アプリケーションから前記関数が呼び出しを受けた場合に前記関数の開始時刻とアドレスを含む関数履歴を記録する入口トレース関数と、前記関数の終了時刻とアドレスを含む関数履歴を記録する出口トレース関数とを用い、
それぞれの前記関数の冒頭に、前記アプリケーションから呼び出された際に前記関数の実行後に戻るべきアドレスをスタックに一時記憶する命令と、前記入口トレース関数を呼び出して実行する命令を加え、
前記アプリケーションから前記関数が呼び出されると、前記関数の開始時に前記入口トレース関数を呼び出して前記関数履歴を取得してサイクリックバッファーに保存してリターンレジスタに前記関数の終了時に前記出口トレース関数の呼び出しを設定し、前記関数に戻って前記関数本体の内容を実行し、前記関数の終了時に前記出口トレース関数を呼び出して前記関数履歴を取得してサイクリックバッファーに保存した後、前記スタックに一時記憶した前記アドレスを手掛かりとして前記アプリケーションに戻ることにより、前記関数履歴のトレース(ファンクショントレース)を実行することを特徴とする利用者システムのリアルタイム診断方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2006237087A JP2008059402A (ja) | 2006-09-01 | 2006-09-01 | リアルタイム診断システムおよびリアルタイム診断方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
JP2006237087A JP2008059402A (ja) | 2006-09-01 | 2006-09-01 | リアルタイム診断システムおよびリアルタイム診断方法 |
Publications (1)
Publication Number | Publication Date |
---|---|
JP2008059402A true JP2008059402A (ja) | 2008-03-13 |
Family
ID=39242034
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
JP2006237087A Pending JP2008059402A (ja) | 2006-09-01 | 2006-09-01 | リアルタイム診断システムおよびリアルタイム診断方法 |
Country Status (1)
Country | Link |
---|---|
JP (1) | JP2008059402A (ja) |
Cited By (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
JP2016110502A (ja) * | 2014-12-09 | 2016-06-20 | 株式会社デンソー | 電子制御装置 |
US10067813B2 (en) | 2014-11-21 | 2018-09-04 | Samsung Electronics Co., Ltd. | Method of analyzing a fault of an electronic system |
CN113448815A (zh) * | 2020-03-26 | 2021-09-28 | 华为技术有限公司 | 一种采集追踪trace调用链的方法和电子设备 |
CN113848843A (zh) * | 2021-10-21 | 2021-12-28 | 万洲电气股份有限公司 | 一种基于智能优化节能系统的自诊断分析系统 |
-
2006
- 2006-09-01 JP JP2006237087A patent/JP2008059402A/ja active Pending
Cited By (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US10067813B2 (en) | 2014-11-21 | 2018-09-04 | Samsung Electronics Co., Ltd. | Method of analyzing a fault of an electronic system |
JP2016110502A (ja) * | 2014-12-09 | 2016-06-20 | 株式会社デンソー | 電子制御装置 |
CN113448815A (zh) * | 2020-03-26 | 2021-09-28 | 华为技术有限公司 | 一种采集追踪trace调用链的方法和电子设备 |
CN113848843A (zh) * | 2021-10-21 | 2021-12-28 | 万洲电气股份有限公司 | 一种基于智能优化节能系统的自诊断分析系统 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US7469362B2 (en) | Using a call stack hash to record the state of a process | |
US8234631B2 (en) | Method and system for tracing individual transactions at the granularity level of method calls throughout distributed heterogeneous applications without source code modifications | |
US8555259B2 (en) | Verifying function performance based on predefined count ranges | |
US7788535B2 (en) | Means and method for debugging | |
US8938729B2 (en) | Two pass automated application instrumentation | |
US7441234B2 (en) | Correlating trace events | |
US7882495B2 (en) | Bounded program failure analysis and correction | |
US7900198B2 (en) | Method and system for parameter profile compiling | |
US7530056B1 (en) | Method and system for detecting runtime defects in a program by comparing correct and incorrect runs | |
US20080127117A1 (en) | Method and apparatus for instrumentation in a multiprocessing environment | |
US20120036501A1 (en) | Method and System for Capturing System and User Events Using Hardware Trace Devices | |
JP2008059402A (ja) | リアルタイム診断システムおよびリアルタイム診断方法 | |
EP2735970B1 (en) | Dynamic library profiling method | |
US11074153B2 (en) | Collecting application state in a runtime environment for reversible debugging | |
US11113182B2 (en) | Reversible debugging in a runtime environment | |
CN112540808A (zh) | 一种程序行为层级调用关系的记录方法及相关设备 | |
García-Gordillo et al. | Heterogeneous runtime monitoring for real-time systems with art2kitekt | |
Sundaram et al. | Diagnostic tracing for wireless sensor networks | |
CN108021495B (zh) | 基于回放的代码调试方法 | |
CN112162908A (zh) | 基于字节码注入技术的程序调用链路监控实现方法及装置 | |
CN116909819A (zh) | 一种处理器调试方法、装置、计算机设备及处理器 | |
US20080109794A1 (en) | Method for Signaling Runtime Events to an Automated Test Script | |
JP7116562B2 (ja) | 追跡データ表現 | |
Sundmark et al. | Monitored software components-a novel software engineering approach | |
KR20020055528A (ko) | 멀티 태스크 프로그램의 논스톱 디버깅을 위한트레이스포인트 설정 방법 |