(57)【要約】【課題】ソフトウェアのデバッグ中にブレークポイントを使用して関数呼び出し毎に実行を中断することなく、末尾呼び出しの最適化が行われた場合のコールスタックを正しく表示することができるソフトウエアデバッグ装置及び方法を提供する。【解決手段】  ソースプログラムをコンパイル処理によって実行イメージプログラムと共に得られたデバッグ情報に応じて実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成し、実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行し、その実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させ、トレースメモリのオペラントとシンボルテーブルのアドレス情報との対応関係に応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示する。【選択図】図８
2010287101.tif 000002
【特許請求の範囲】
【請求項１】
ソースプログラムをコンパイル処理してデバッグ情報と共に生成された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ装置であって、
前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成手段と、
前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行手段と、
前記プログラム実行手段による実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させるトレース手段と、
前記トレースメモリのオペラントと前記シンボルテーブルのアドレス情報との対応関係に応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示手段と、を備えることを特徴とするソフトウエアデバッグ装置。
【請求項２】
前記シンボルテーブルには前記アドレス情報として関数の開始アドレスとアドレスサイズとが含まれ、
前記コールスタック表示手段は、前記シンボルテーブルの開始アドレスが前記トレースメモリのオペラントに使用されている前記分岐命令である場合にはその開始アドレスの関数名を前記シンボルテーブルから取得し、
前記トレースメモリに関数からの復帰命令が記憶されている場合にはその復帰命令の復帰先アドレスが前記シンボルテーブルに含まれている関数の開始アドレスから前記アドレスサイズのアドレス範囲に含まれているならば、その開始アドレスの関数名を前記シンボルテーブルから取得することを特徴とする請求項1記載のソフトウエアデバッグ装置。
【請求項３】
操作に応じて前記プログラム実行手段の実行動作が中断されたとき前記コールスタック表示手段は前記コールスタックを作成することを特徴とする請求項１記載のソフトウエアデバッグ装置。
【請求項４】
ソースプログラムをコンパイル処理してデバッグ情報と共に生成された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ方法であって、
前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成ステップと、
前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行ステップと、
前記プログラム実行ステップによる実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させるトレース手段と、
前記トレースメモリのオペラントと前記シンボルテーブルのアドレス情報との対応関係に応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示ステップと、を備えることを特徴とするソフトウエアデバッグ方法。
【請求項５】
ソースプログラムをコンパイル処理してデバッグ情報と共に生成され、関数呼び出しの分岐命令の直前に、関数呼び出しがあることを表す第１擬似命令が配置され、その関数呼び出しのうち末尾呼び出しの最適化が適用された場合には前記第１擬似命令に代えて第２擬似命令が配置された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ装置であって、
前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成手段と、
前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行手段と、
前記ソースプログラムに対して静的解析を施して関数の呼び出し関係を示す関数コールツリーを作成する関数コールツリー作成手段と、
前記実行イメージプログラム中の前記第１擬似命令及び前記第２擬似命令、前記関数コールツリー並び前記シンボルテーブルに基づいて前記末尾呼び出しの最適化が適用された関数、その復帰元関数及び戻りアドレスからなる戻りアドレステーブルを作成する戻りアドレステーブル作成手段と、
前記プログラム実行手段による命令実行によりリンクレジスタに格納された戻りアドレスと前記戻りアドレステーブルとに応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示手段と、を備えることを特徴とするソフトウエアデバッグ装置。
【請求項６】
前記戻りアドレステーブル作成手段は、前記実行イメージプログラム中の前記第２擬似命令がプログラムコードとして存在する関数がある場合には、前記コールツリーに応じて前記第２擬似命令が存在する関数を呼び出している関数を検出し、
前記呼び出している関数のプログラムコード中に前記第１擬似命令が存在する場合には、その直後の分岐命令のオペラントが示すアドレスを前記戻りアドレスとし、その戻りアドレスに応じて前記シンボルテーブルを検索して前記復帰元関数及び前記末尾呼び出しの最適化が適用された関数を検出することを特徴とする請求項５記載のソフトウエアデバッグ装置。
【請求項７】
前記コールスタック表示手段は、前記リンクレジスタに格納された戻りアドレスが前記戻りアドレステーブルに存在する場合には前記戻りアドレステーブルからその戻りアドレスについての前記末尾呼び出しの最適化が適用された関数の関数名を読み出して前記コールスタックを作成することを特徴とする請求項５記載のソフトウエアデバッグ装置。
【請求項８】
操作に応じて前記プログラム実行手段の実行動作が中断されたとき前記コールスタック表示手段は前記コールスタックを作成することを特徴とする請求項５又は７記載のソフトウエアデバッグ装置。
【請求項９】
ソースプログラムをコンパイル処理してデバッグ情報と共に生成され、関数呼び出しの分岐命令の直前に、関数呼び出しがあることを表す第１擬似命令が配置され、その関数呼び出しのうち末尾呼び出しの最適化が適用された場合には前記第１擬似命令に代えて第２擬似命令が配置された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ方法であって、
前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成ステップと、
前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行ステップと、
前記ソースプログラムに対して静的解析を施して関数の呼び出し関係を示す関数コールツリーを作成する関数コールツリー作成ステップと、
前記実行イメージプログラム中の前記第１擬似命令及び前記第２擬似命令、前記関数コールツリー並び前記シンボルテーブルに基づいて前記末尾呼び出しの最適化が適用された関数、その復帰元関数及び戻りアドレスからなる戻りアドレステーブルを作成する戻りアドレステーブル作成ステップと、
前記プログラム実行ステップによる命令実行によりリンクレジスタに格納された戻りアドレスと前記戻りアドレステーブルとに応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示ステップと、を備えることを特徴とするソフトウエアデバッグ方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ソフトウェアのデバッグにおいて高級言語レベルで実行された関数の履歴を取得するソフトウエアデバッグ装置及び方法に関するものである。
【背景技術】
【０００２】
ソフトウェアのデバッグ中に、プログラム実行中の任意の時点で処理を実行している関数がどの関数から呼ばれたものなのかを知るために、コールスタックの機能が用いられる。コールスタックは、プログラムの実行開始から現在実行している関数が呼び出されるまでの関数呼び出しの階層を表示する機能である。
【０００３】
例えば、Ｃ言語のプログラムにおいて、図１に示すように３つの関数main、func1、func2が定義されている場合に、プログラム実行時には、main→func1→func2の順に関数が呼び出される。
【０００４】
このプログラムをソースコードレベルでデバッグする際、func2の実行中にデバッガのコールスタックウィンドウを開くと、デバッガは、図２に示すようにfunc2が呼び出されるまでの関数呼び出しの階層を表示し、現在実行中の関数を例えば、矢印でマークして表示する。
【０００５】
一般に、このようなコールスタックの情報を表示するためには、デバッガはスタックの内容を解析する必要がある。例として、次に、図１に示したようなプログラムの実行におけるスタックの動作とその解析方法を説明する。
【０００６】
先ず、図１に示したようなソースコードに対して、コンパイラは図３に示すようなアセンブリコードを出力する。このアセンブリコードにおいて、bl命令が関数呼び出しを実行する命令である。この命令により、関数の先頭アドレスへの分岐と、復帰アドレスのリンクレジスタlrへの設定とが行われる。mainとfunc1の先頭では"push lr"の命令があるが、これは、その後に実行されるbl命令によりリンクレジスタlrが上書きされるため、その内容をスタックに退避させる命令である。また、この命令の後、各関数の処理に入る前に、各関数が使用するローカル変数用の領域とワークレジスタ退避用の領域がスタックに確保される。このように、各関数が使用するためにスタック内に確保した領域をスタックフレームと呼ぶ。各関数のスタックフレームのサイズは、コンパイラがアセンブリコードを生成するときに一緒に出力されるデバッグ情報から知ることができる。mainからfunc1→func2の順に関数が呼び出され、func2内の処理を実行途中の状態ではスタックの内容は図４に示すようになる。
【０００７】
コールスタックを表示する場合には、デバッガはプログラムカウンタ(PC)の値を読み出し、その内容がfunc2の関数内のアドレスであることから、func2の実行中であることを知ることができる。次に、コンパイラが出力したfunc2のデバッグ情報から、func2の復帰アドレスがリンクレジスタlrに格納されていることが分かるので、lrからその復帰アドレスを読み出す。この復帰アドレスがどの関数内のアドレスであるかを調べることにより、func2がfunc1から呼び出されていることを知ることができる。
【０００８】
更に、func1のデバッグ情報を調べることにより、func1の復帰アドレスはスタックに退避されていることが分かる。退避されているスタック内のアドレスは、現在のスタックポインタが指すアドレスからfunc1及びfunc2のスタックフレームのサイズを差し引くことにより算出することができる。この算出したアドレスからfunc1の復帰アドレスを読み出すと、そのアドレスがmain関数内のアドレスであることが分かり、func1がmainから呼び出されていることを知ることができる。このようにして、デバッガは図２に示したようなコールスタックを表示する。
【先行技術文献】
【特許文献】
【０００９】
【特許文献１】特開平１１−０６５８８５号公報
【発明の概要】
【発明が解決しようとする課題】
【００１０】
しかしながら、上記のような方法では、コンパイラにより出力アセンブリコードが最適化されるときに、正しくコールスタックを表示できない場合がある。
【００１１】
正しくコールスタックを表示できない場合の例として、コンパイラによる関数の「末尾呼び出しの最適化」が挙げられる。
【００１２】
末尾呼び出しの最適化とは、図１の中の関数func1のように、関数の末尾で関数func2を呼び出している場合に実施される最適化である。このfunc2の呼び出しは、func1の末尾で実施されているため、func2の処理を終えてfunc1に戻ってきても、その後、mainに戻るだけである。そこで、コンパイラは、func2からfunc1に戻らず直接mainに戻るように、func2の呼び出し前にfunc1のスタックフレームを破棄し、func2の呼び出しを行う。このfunc2の呼び出しを実行するための分岐命令は、戻り番地をリンクレジスタlrに設定しない分岐命令(b命令)が使用される。すなわち、リンクレジスタlrには、mainからfunc1が呼び出されたときに設定されたリンクレジスタlrの値が格納されたままになる。func2から戻るときは、このリンクレジスタlrの値が戻りアドレスとして使用されるため、func1には戻らず直接mainに戻ることができ、func1に戻る分の処理時間のオーバヘッドを減らすことができる。この末尾呼び出しの最適化が実施された場合のアセンブリコードは図５に示されている。
【００１３】
図５に示すようなアセンブリコードにおいては、func2を実行中のスタックの内容は図６に示すようになる。
【００１４】
この状態においてコールスタックを表示する場合には、先ず、デバッガはプログラムカウンタ(PC)の値を読み出し、その内容がfunc2の関数内のアドレスであることから、func2の実行中であることを知ることができる。次に、コンパイラが出力したfunc2のデバッグ情報から、func2の復帰アドレスがリンクレジスタlrに格納されていることが分かるので、リンクレジスタlrからその復帰アドレスを読み出す。この復帰アドレスがどの関数内のアドレスであるかを調べることにより、呼び出し元の関数を知ることができるが、図５に示したように最適化が実施されている場合には、func2を実行している状態でリンクレジスタlrに格納されているのはmain関数内のアドレスである。従って、このような場合は、デバッガはfunc2がmainから呼び出されたものを判定してしまうため、コールスタックにはmainからfunc2の呼び出しまでの間にfunc1が呼び出されていることの情報が出力されなくなるという問題が発生する。このときのコールスタックの表示は図７に示すようになる。
【００１５】
このように、コンパイラの末尾呼び出しの最適化が行われた場合、実際にはfunc2はfunc1から呼び出されたものであるにもかかわらず、その情報が欠落した誤った表示となるため、コールスタックを使ってデバッグを行う場合はデバッグの作業の効率を低下させる要因となる。
【００１６】
コンパイラによる最適化が実施された場合に正しくコールスタックを表示させる方法としては、特許文献１に挙げられている従来の方法がある。この従来の方法は、全ての関数の先頭アドレスと最終アドレスとにソフトウェアブレークポイントを設定し、それぞれのブレークポイントでブレークしたときに関数の情報を取得するという方法である。
【００１７】
しかしながら、この従来の方法では、プログラム実行中に関数呼び出しが発生する度にブレークして実行が中断されるため、デバッグ中の実行においてリアルタイム性が損なわれるという別の問題がある。
【００１８】
そこで、本発明の目的は、ソフトウェアのデバッグ中にブレークポイントを使用して関数呼び出し毎に実行を中断することなく、末尾呼び出しの最適化が行われた場合のコールスタックを正しく表示することができるソフトウエアデバッグ装置及び方法を提供することである。
【課題を解決するための手段】
【００１９】
本願の請求項１に係る発明のソフトウエアデバッグ装置は、ソースプログラムをコンパイル処理してデバッグ情報と共に生成された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ装置であって、前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成手段と、前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行手段と、前記プログラム実行手段による実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させるトレース手段と、前記トレースメモリのオペラントと前記シンボルテーブルのアドレス情報との対応関係に応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示手段と、を備えることを特徴としている。
【００２０】
本願の請求項４に係る発明のソフトウエアデバッグ方法は、ソースプログラムをコンパイル処理してデバッグ情報と共に生成された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ方法であって、前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成ステップと、前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行ステップと、前記プログラム実行ステップによる実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させるトレース手段と、前記トレースメモリのオペラントと前記シンボルテーブルのアドレス情報との対応関係に応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示ステップと、を備えることを特徴としている。
【００２１】
本願の請求項５に係る発明のソフトウエアデバッグ装置は、ソースプログラムをコンパイル処理してデバッグ情報と共に生成され、関数呼び出しの分岐命令の直前に、関数呼び出しがあることを表す第１擬似命令が配置され、その関数呼び出しのうち末尾呼び出しの最適化が適用された場合には前記第１擬似命令に代えて第２擬似命令が配置された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ装置であって、前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成手段と、前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行手段と、前記ソースプログラムに対して静的解析を施して関数の呼び出し関係を示す関数コールツリーを作成する関数コールツリー作成手段と、前記実行イメージプログラム中の前記第１擬似命令及び前記第２擬似命令、前記関数コールツリー並び前記シンボルテーブルに基づいて前記末尾呼び出しの最適化が適用された関数、その復帰元関数及び戻りアドレスからなる戻りアドレステーブルを作成する戻りアドレステーブル作成手段と、前記プログラム実行手段による命令実行によりリンクレジスタに格納された戻りアドレスと前記戻りアドレステーブルとに応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示手段と、を備えることを特徴としている。
【００２２】
本願の請求項９に係る発明のソフトウエアデバッグ方法は、ソースプログラムをコンパイル処理してデバッグ情報と共に生成され、関数呼び出しの分岐命令の直前に、関数呼び出しがあることを表す第１擬似命令が配置され、その関数呼び出しのうち末尾呼び出しの最適化が適用された場合には前記第１擬似命令に代えて第２擬似命令が配置された実行イメージプログラムのデバッグ処理を行うソフトウエアデバッグ方法であって、前記デバッグ情報に応じて前記実行イメージプログラム中の関数毎の関数名及びアドレス情報をシンボルテーブルとして作成するシンボルテーブル作成ステップと、前記実行イメージプログラムのプログラムコード順にプログラムコードの命令を実行するプログラム実行ステップと、前記ソースプログラムに対して静的解析を施して関数の呼び出し関係を示す関数コールツリーを作成する関数コールツリー作成ステップと、前記実行イメージプログラム中の前記第１擬似命令及び前記第２擬似命令、前記関数コールツリー並び前記シンボルテーブルに基づいて前記末尾呼び出しの最適化が適用された関数、その復帰元関数及び戻りアドレスからなる戻りアドレステーブルを作成する戻りアドレステーブル作成ステップと、前記プログラム実行ステップによる命令実行によりリンクレジスタに格納された戻りアドレスと前記戻りアドレステーブルとに応じて関数呼び出しの階層を示すコールスタックを作成してそれを表示するコールスタック表示ステップと、を備えることを特徴としている。
【発明の効果】
【００２３】
本願の請求項１に係る発明のソフトウエアデバッグ装置及び請求項５に係る発明のソフトウエアデバッグ方法によれば、プログラムコードの実行命令が分岐命令である場合にその分岐命令のプログラムコードをオペラントを含めてトレースメモリに記憶させるので、トレースメモリに格納して分岐トレースの機能を利用することにより、コンパイラによって末尾呼び出し最適化が行われた場合にもデバッグ中に関数呼び出し毎に実行を中断することなく、コールスタックを正しく表示することができる。
【００２４】
本願の請求項５に係る発明のソフトウエアデバッグ装置及び請求項９に係る発明のソフトウエアデバッグ方法によれば、ソースプログラムに対して静的解析を施して関数の呼び出し関係を示す関数コールツリーが作成され、また、実行イメージプログラム中の第１擬似命令及び前記第２擬似命令、関数コールツリー並びシンボルテーブルに基づいて末尾呼び出しの最適化が適用された関数、その復帰元関数及び戻りアドレスからなる戻りアドレステーブルが作成されるので、リンクレジスタに格納された戻りアドレスとシンボルテーブル又は戻りアドレステーブルとを用いることにより、コンパイラによって末尾呼び出し最適化が行われた場合にもデバッグ中に関数呼び出し毎に実行を中断することなく、コールスタックを正しく表示することができる。
【図面の簡単な説明】
【００２５】
【図１】プログラムに定義された３つの関数の呼び出し関係を示す図である。
【図２】デバッグにおけるコールスタックの表示例を示す図である。
【図３】コンパイラの出力アセンブリコード例を示す図である。
【図４】スタックフレームの例を示す図である。
【図５】末尾呼び出しの最適化が実施された場合のコンパイラの出力アセンブリコード例を示す図である。
【図６】末尾呼び出しの最適化が実施された場合のスタックフレームの例を示す図である。
【図７】末尾呼び出しの最適化が実施された場合のコールスタックの表示例を示す図である。
【図８】本発明の第１の実施例としてソフトウエアデバッグ装置の構成を示すブロック図である。
【図９】シンボルテーブルの内容を示す図である。
【図１０】トレースメモリの内容を示す図である。
【図１１】関数から復帰後のトレースメモリの内容を示す図である。
【図１２】main関数へ復帰後のコールスタックの表示例を示す図である。
【図１３】本発明の第２の実施例としてソフトウエアデバッグ装置の構成を示すブロック図である。
【図１４】プログラムに定義された３つの関数の呼び出し関係を示す図である。
【図１５】関数コールツリーを示す図である。
【図１６】末尾呼び出しの最適化が実施された場合のコンパイラの出力アセンブリコード例を示す図である。
【図１７】戻りアドレステーブルを示す図である。
【発明を実施するための形態】
【００２６】
以下、本発明の実施例を図面を参照しつつ詳細に説明する。
【００２７】
図８は、本発明の第１の実施例としてソフトウエアデバッグ装置の構成を示している。ソフトウエアデバッグ装置は、デバッガ１１とデバッグターゲット１２とを備えている。デバッガ１１はデバッガ制御部２１、シンボルテーブル２２及びコールスタック表示部２３を備えている。
【００２８】
デバッガ制御部２１はシンボルテーブル２２及びコールスタック表示部２３の各々接続されている。シンボルテーブル２２はメモリからなる。シンボルテーブル作成手段はデバッガ制御部２１及びシンボルテーブル２２からなる。
【００２９】
また、デバッガ制御部２１は後述の実行イメージプログラム（実行形式プログラム）４６をデバッグ情報４７と共に読み出して実行イメージプログラム４６からプログラムコードを抽出し、そのプログラムコードをデバッグターゲット１２に出力する。また、デバッガ制御部２１は読み出したデバッグ情報４７から関数を抽出し、関数の名前、関数の開始アドレス及び関数に含まれる命令コードの合計サイズをシンボルテーブル２２に格納（記憶）させる。コールスタック表示部２３はデバッガ制御部２１の指令に応じて図示しない表示器にコールスタックを表示する。コールスタック表示手段はデバッガ制御部２１及びコールスタック表示部２３からなる。
【００３０】
デバッグターゲット１２はデバッグインターフェース３１、プログラムメモリ３２、プログラム実行部３３及びトレースメモリ３４を備えている。デバッグインターフェース３１はプログラムメモリ３２、プログラム実行部３３及びトレースメモリ３４の各々に接続され、プログラム実行部３３はプログラムメモリ３２及びトレースメモリ３４各々に接続されている。
【００３１】
デバッグインターフェース３１はデバッガ１１のデバッガ制御部２１とのプログラムコード等の情報の入出力のために設けられている。
【００３２】
プログラムメモリ３２には上記のプログラムコードが供給順に格納される。プログラム実行部３３はプログラム実行手段であり、プログラムメモリ３２に格納されたプログラムコードの命令を順に実行する。また、プログラム実行部３３はプログラム実行中に命令が分岐命令であるときに、実行した分岐命令の命令コードをオペランドの情報を含めてトレースメモリ３４に格納するトレース手段を含んでいる。
【００３３】
かかるソフトウエアデバッグ装置においては、コールスタックの情報を表示する際に、ターゲットの分岐トレースの情報を利用する。分岐トレースとは、プログラム実行部３３がプログラム実行中に分岐命令を実行した時に、実行した分岐命令の命令コードを実行した順番にトレースメモリ３４に格納する機能である。この機能により、トレースメモリ３４には、実行した分岐命令の履歴データが格納されることになる。
【００３４】
デバッガ制御部２１は、実行イメージプログラム４６をデバッグ情報４７と共に取り込んだときに、デバッグ情報４７に含まれるシンボルテーブル２２を取得し、シンボルテーブル２２から実行イメージプログラム４６に含まれる関数の名前とアドレスとの対応関係を検出する。従って、トレースメモリ３４から取得した各分岐命令のオペランドから分岐先アドレスを取得し、そのアドレスで特定される関数がシンボルテーブル２２に含まれていれば、その分岐命令は関数呼び出しであると判断できる。そして、トレースメモリ３４から関数呼び出しに相当する分岐命令を検出すれば、それは関数の呼び出しの履歴として解釈することができ、その履歴情報から表示すべきコールスタックの情報を生成する。コールスタックの情報はコールスタック表示部２３に供給されて表示される。
【００３５】
次に、かかるソフトウエアデバッグ装置において、末尾呼び出しの最適化が実施されたプログラムをデバッグする場合について説明する。
【００３６】
先ず、Ｃソースファイル（Ｃソースプログラム）４１からコード生成ツール４２のコンパイラ４３、アセンブラ４４及びリンカ４５により実行イメージプログラム４６が生成され、その実行イメージプログラム４６はデバッグ情報４７と共に格納されている。なお、コンパイラ４３はＣソースファイル４１からアセンブリブログラムを生成し、アセンブラ４４はそのアセンブリプログラムをオブジェクトファイルに変換し、リンカ４５はそのアセンブラ４４によって得られたオブジェクトファイルに基づいて実行イメージプログラム４６を生成する。これらのコード生成ツール４２においてはデバッグ情報４７が生成されるようにいわゆるオプションが付けられる。
【００３７】
デバッガ１１のデバッガ制御部２１は実行イメージプログラム４６からプログラムコードを抽出する。抽出されたプログラムコードは順にデバッグターゲット１２のデバッグインターフェース部３１を介して、プログラムメモリ３２に格納される。プログラムメモリ３２に格納されたプログラムコード群をプログラムと称す。また、同時にデバッガ制御部２１は実行イメージプログラム４６のデバッグ情報４７から関数を抽出して、図９に示すような関数のシンボルテーブル２２を形成する。このシンボルテーブル２２には、関数の名前と、関数の開始アドレス及び関数に含まれる命令コードの合計サイズの情報が含まれている。
【００３８】
プログラムメモリ３２にプログラムが格納された後、デバッグインターフェース部３１を介して供給されるデバッガ制御部２１の指令に応じて、プログラム実行部３３によりそのプログラム中の命令が順に実行される。プログラム実行部３３は、実行した命令が分岐命令だった場合に、同時にその命令コードをオペランドの情報を含めてトレースメモリ３４に格納する。例えば、func2の実行中にデバッガ１１への操作に応じてプログラムの実行が中断(ブレーク)したときのトレースメモリ３４の内容は図１０に示すようになる。
【００３９】
デバッガ制御部２１は、先ず、トレースメモリ３４の内容を取得し、図９のシンボルテーブル２２のアドレスの値が、トレースメモリ３４内の分岐命令のオペランドに使用されていないか調査する。すなわち、トレースメモリ３４のオペラントとシンボルテーブル２２のアドレス情報との対応関係を検出することが行われる。図９及び図１０の例の場合においては、この調査の結果、デバッガ制御部２１は、図１０のIndex2の分岐命令が関数mainの呼び出しであり、Index3の分岐命令が関数func1の呼び出しであり、更に、Index4の分岐命令が関数func2の呼び出しであることを検出することができる。Index1の分岐命令は、そのオペランドのアドレスがシンボルテーブル２２のアドレスの値と一致するものがないため、関数呼び出しではないと判断することができる。デバッガ制御部２１は、関数呼び出しであると判断できた分岐命令のIndexの大きい順に分岐先の関数名を並べて表示することにより、コールスタック表示部２３には図２に示したようにコールスタックが表示される。
【００４０】
次に、デバッガ動作を続けて実行させて、func2からmainまで戻った時点でプログラム実行をブレークさせた場合には、トレースメモリ３４の内容は図１１に示すようになったとする。
【００４１】
トレースメモリ３４のIndex5には、関数func2からの復帰となる分岐命令であるrt命令と、その分岐先アドレスの情報が格納される。デバッガ制御部２１は、トレースメモリ３４の中に関数からの復帰命令を見つけると、その復帰先のアドレスがどの関数の範囲内にあるかを調べるため、シンボルテーブル２２を調査する。図１１の例では復帰先アドレスが0x1020であり、図９の情報からmain関数の先頭アドレス0x1000からそのサイズ0x40進んだアドレスまでの範囲に含まれるため、main関数内のアドレスであることが分かる。
【００４２】
このとき、コールスタックを表示する場合には、デバッガ制御部２１は前述と同様に、トレースメモリ３４の内容を調べ、関数呼び出しであると判断できた分岐命令のIndexの大きい順に分岐先の関数名を並べて表示しようとする。しかしながら、Index5の復帰命令により現在main関数に戻ってきていることが分かるので、mainの呼び出しを表すIndex2からIndex5の間の関数呼び出し、(すなわちIndex3のfunc1とIndex4のfunc2)は、既にその関数の実行が終了しているとみなすことができる。よって、コールスタック表示部２３に表示するコールスタックは、トレースメモリのIndex3及びIndex4に相当する関数を省いた図１２に示すようにmain関数のみの表示となる。
【００４３】
以上のように、第１の実施例によれば、デバッグターゲット１２に付加された、分岐命令のみをトレースメモリ３４に格納する分岐トレースの機能を利用することにより、コンパイラ４３の末尾呼び出し最適化が行われた場合にも正しくコールスタックを表示させることができる。また、コールスタックの表示に必要な関数呼び出しの履歴情報を取得するために関数呼び出し毎にプログラムをブレークさせることがないため、プログラム実行中のリアルタイム性を損なうことがない。更に、分岐トレース機能は、通常のトレース機能に比べてトレースメモリ３４に格納する情報は分岐命令のみであるため、トレースメモリ３４の容量も小さくて済むため、大きなコスト増加にはならないという利点がある。
【００４４】
図１３は本発明の第２の実施例としてソフトウエアデバッグ装置の構成を示している。ソフトウエアデバッグ装置は、図８の第１の実施例の装置と同様に、デバッガ１１とデバッグターゲット１２とを備えている。デバッガ１１はデバッガ制御部２１、シンボルテーブル２２及びコールスタック表示部２３の他に、戻りアドレステーブル２４を備えている。戻りアドレステーブル２４には戻りアドレスが格納される。デバッガ制御部２１及び戻りアドレステーブル２４が戻りアドレステーブル作成手段を構成している。
【００４５】
デバッグターゲット１２はデバッグインターフェース３１、プログラムメモリ３２及びプログラム実行部３３を備えている。トレースメモリ３４は備えられていない。
【００４６】
また、かかるソフトウエアデバッグ装置は、関数コールツリー生成部１３と関数コールツリーメモリ１４とを備えている。関数コールツリー生成部１３はＣソースファイル４１を静的に解析し、関数の呼び出し関係を表すコールツリー１４を関数コールツリーメモリ１５に出力する関数コールツリー作成手段である。関数コールツリー１４は、関数の呼び出し関係をツリー構造で表現したものであり、例えば、図１４に示すようソースプログラムからは、関数コールツリー１４として図１５に示すような出力が得られる。図１４に示したソースプログラム４１では、main2関数からfunc1とfunc2が呼び出されており、更にfunc1からはfunc2が呼び出されている。この呼び出し関係は、コンパイラ４３により最適化される前のＣソースプログラム４１上での呼び出し関係を表している。
【００４７】
更に、かかるソフトウエアデバッグ装置において、コンパイラ４３は、末尾呼び出しの最適化を行った関数の出力アセンブリコードに、末尾呼び出しの最適化が行われたことを表す擬似命令を出力する。デバッガ１１は、この擬似命令の有無と、関数コールツリーの情報により、どの関数に末尾呼び出し最適化されているか知ることができるため、正しくコールスタックを表示できるようになる。
【００４８】
次に、かかるソフトウエアデバッグ装置において、末尾呼び出しの最適化が実施されたプログラムをデバッグする場合について説明する。
【００４９】
先ず、Ｃソースファイル４１からコード生成ツール４２のコンパイラ４３、アセンブラ４４及びリンカ４５により実行イメージプログラム４６が作成され、その実行イメージプログラム４６はデバッグ情報４７と共に格納されている。
【００５０】
ここで、コンパイラ４３がＣソースプログラム４１からアセンブリプログラムを生成する際においては、図１６に示すように、関数呼び出しの分岐命令の直前に、関数呼び出しがあることを表す擬似命令FUNCCALL（第１疑似命令）が配置され、また、末尾呼び出しの最適化が適用された関数呼び出しにはTAILCALL擬似命令（第２疑似命令）が配置される。これらの擬似命令は、アセンブラ４４及びリンカ４５により実行イメージプログラム４６の中にその情報が埋め込まれる。一方、関数コールツリー生成部１３により、Ｃソースプログラム４１の静的解析が行われ、関数コールツリーが出力される。
【００５１】
次に、デバッガ１１では、第１の実施例と同様に、実行イメージプログラム４６からプログラムコードをプログラムメモリ３２にダウンロードするとともに、関数のシンボルテーブル２２を抽出することが行われる。
【００５２】
このとき、デバッガ制御部２１は実行イメージプログラム４６内の各関数内のプログラムコードにTAILCALL擬似命令があるか否かを調査する。この調査において、デバッガ制御部２１はTAILCALL擬似命令が見つかった場合には、関数コールツリー１４を調べて、それが存在する関数を呼び出している関数を検出する。
【００５３】
図１６に示すようなアセンブリコードについては、func1関数のプログラムコードの中にTAILCALL擬似命令が見つかる。そして関数コールツリー１４の中からfunc1を呼び出している関数を探し出す。図１５の例では、main2がfunc1を呼び出している関数に相当する。
【００５４】
次に、デバッガ制御部２１は、TAILCALL擬似命令を持つfunc1関数を呼び出しているmain2関数のプログラムコードの中でfunc1を呼び出している位置（アドレス）を探す。これは、main2の中から関数呼び出しを表すFUNCCALL擬似命令を探し、その直後の分岐命令のオペランド(分岐先アドレス)を調べ、その分岐先アドレスが、シンボルテーブル２２に登録されているfunc1のアドレスと一致すれば、func1を呼び出す分岐命令であると分かる。func1への分岐命令が見つかったら、その直後のアドレスがfunc1から戻るはずの戻り番地になる。
【００５５】
ただし、実際には末尾呼び出しの最適化が行われているので、この戻り番地は、TAILCALL擬似命令の直後の分岐命令で呼び出される関数からの戻り番地と解釈することができる。図１６の例では、戻りアドレスは0x1020であったとする。TAILCALL擬似命令の直後の分岐命令で呼び出される関数は、その分岐命令のオペランド(分岐先アドレス)をシンボルテーブル２２から検索することにより、func2関数であることが分かる。従って、戻りアドレス0x1020は、実際はfunc2からの戻りアドレスとなる。そこで、デバッガ制御部２１はこのアドレス0x1020と、実際の復帰元関数であるfunc2と、末尾呼び出しの最適化が実施された関数func1とを戻りアドレステーブル２４に登録しておく。よって、戻りアドレステーブルの内容は図１７に示すように戻りアドレスと復帰元関数func2と、最適化が実施されたfunc1が登録される。
【００５６】
このようにして、TAILCALL擬似命令を持つすべての関数について、その呼び出し元の関数と戻りアドレスが、戻りアドレステーブルに登録される。
【００５７】
戻りアドレステーブル作成の実行後、デバッガ制御部２１はデバッグインターフェース３１を介してプログラム実行部３３にプログラムを実行させる。
【００５８】
そして、例えば、func2の実行中にデバッガ１１に対する操作によりプログラムの実行が中断(ブレーク)したとする。ここで、そのブレークに応答してコールスタックを表示する場合には、最初にデバッガ制御部２１は、上記の背景技術の欄で説明したように、func2からの戻りアドレスをリンクレジスタlrから読み出す。そして、リンクレジスタlrに格納されていたアドレスが図１７の戻りアドレステーブル２４に登録されていれば、その戻りアドレステーブル２４の内容からfunc2が呼び出されるまでの間にfunc1の呼び出しがあったことが分かるので、デバッガ制御部２１はコールスタックにfunc1の呼び出し履歴を追加して、図２に示したような表示を得ることが行われる。なお、リンクレジスタlrに格納されていたアドレスが戻りアドレステーブル２４に登録されていない場合には上記の背景技術の欄に示したように、スタックフレームを用いて戻りアドレスがどの関数内のアドレスかを調べることにより呼び出された関数を判別することが行われる。
【００５９】
かかる第２の実施例によれば、第１の実施例のようにデバッグターゲット１２が分岐トレース機能を持たない場合において、関数コールツリー生成部１３が追加されているので、末尾呼び出しの最適化が実施されたプログラムについてもコールスタックが正しく表示することができる。また、関数コールツリー生成部１３はソフトウェア処理として追加されるだけであり、デバッグターゲット１２の内部にトレースメモリのような専用ハードウェアを設けないで済むので、ハードウェアのコストを下げることができる。
【００６０】
使用するデバッグターゲットが分岐トレースの機能を有する場合には第１の実施例の構成を利用することができ、分岐トレースの機能を有しない場合には第２の実施例の構成を選択して利用することができる。
【図１】
2010287101.tif 000003
【図２】
2010287101.tif 000004
【図３】
2010287101.tif 000005
【図４】
2010287101.tif 000006
【図５】
2010287101.tif 000007
【図６】
2010287101.tif 000008
【図７】
2010287101.tif 000009
【図８】
2010287101.tif 000010
【図９】
2010287101.tif 000011
【図１０】
2010287101.tif 000012
【図１１】
2010287101.tif 000013
【図１２】
2010287101.tif 000014
【図１３】
2010287101.tif 000015
【図１４】
2010287101.tif 000016
【図１５】
2010287101.tif 000017
【図１６】
2010287101.tif 000018
【図１７】
2010287101.tif 000019