(57)【要約】【課題】ｃｏｒｅファイルの解析調査において、ローカルシンボルや大域アドレス値の復元などのスタックフレームの解析を自動で行うツールを作成すること。【解決手段】コンパイラ及びリンカに　ｃｏｒｅ　解析のために必要な情報をテーブル形式で出力させ、それらのテーブルから得られるアドレス値からｃｏｒｅファイルを検索し、データを復元する。【選択図】　図１
2004133827.tif 000002
【特許請求の範囲】
【請求項１】
プログラム障害時に生成されたｃｏｒｅファイルに対して、当該プログラムをコンパイルした際にコンパイラが生成した情報と、当該プログラムをリンクした際にリンカが生成した情報を利用し、バックトレースを実行することで各関数の実行時スタックポインタを含むバックトレースリストを取得する手段と、前記スタックポインタからローカルシンボルのアドレスを解決する手段と、前記スタックポインタから大域レジスタ値を復元する手段と、外部からの要求に応じて自身の持つ機能を実行し、結果を出力するインターフェース機能を備えることを特徴とするｃｏｒｅファイル解析装置。
【請求項２】
プログラム障害時に生成されたｃｏｒｅファイルに対して、当該プログラムをコンパイルした際にコンパイラが生成した情報と、当該プログラムをリンクした際にリンカが生成した情報を利用し、バックトレースを実行することで各関数の実行時スタックポインタを含むバックトレースリストを取得する手段を備えることを特徴とするｃｏｒｅファイル解析装置。
【請求項３】
プログラム障害時に生成されたｃｏｒｅファイルに対して、当該プログラムをコンパイルした際にコンパイラが生成した情報と、当該プログラムをリンクした際にリンカが生成した情報を利用し、バックトレースを実行することで各関数の実行時スタックポインタを含むバックトレースリストを取得する手段と、前記スタックポインタからローカルシンボルのアドレスを解決する手段を備えることを特徴とするｃｏｒｅファイル解析装置。
【請求項４】
プログラム障害時に生成されたｃｏｒｅファイルに対して、当該プログラムをコンパイルした際にコンパイラが生成した情報と、当該プログラムをリンクした際にリンカが生成した情報を利用し、バックトレースを実行することで各関数の実行時スタックポインタを含むバックトレースリストを取得する手段と、前記スタックポインタから大域レジスタ値を復元する手段を備えることを特徴とするｃｏｒｅファイル解析装置。
【発明の詳細な説明】
【０００１】
【発明の属する技術分野】
本発明は、プログラムが障害発生などの理由によりアベンドした際に出力するｃｏｒｅファイルを解析するｃｏｒｅ解析装置に関する。
【０００２】
【従来の技術】
プログラム内で使用されるシンボルの属性は、大別してグローバルシンボルとローカルシンボルに分けることができる。グローバルシンボルに関しては、プログラムのリンク時にそのシンボル名称や仮想アドレス空間上での位置情報が必要となるため、それらの情報がコンパイル時に生成されるオブジェクトモジュール内に保存されている。そのため、障害発生時のｃｏｒｅ解析において、それらグローバルシンボルに関してはシンボル名からそのシンボルが表す実データを参照することが可能であった。しかし、ローカルシンボルに関しては、プログラムのリンク時にそのシンボル名称や位置情報を必要としないことから、オブジェクトモジュール生成時にはそれらのシンボル情報は破棄されている。また、ローカルシンボルが参照するデータ領域は、プログラムの実行時にスタック上に動的に割り当てられることや、コンパイル時の最適化によってローカルシンボルをスタック上に退避する命令が削除されてしまうことがあるため、ｃｏｒｅ解析時にそれらの値を復元することは困難であった。ｃｏｒｅ解析時にローカルシンボルを参照したい場合には、プログラムのコンパイル時にデバッガ支援オプションを付加して最適化の抑止及びシンボル情報の保存をコンパイラに指示するか、特許文献記載のようにローカルシンボルを退避するための、本来の処理とは関係の無い命令をオブジェクトコードに付加する必要があった。
【特許文献】
特開平８−２４９１９２号公報
【０００３】
【発明が解決しようとする課題】
実際に製品として出荷されるプログラムには最適化が施されており、ローカルシンボルを退避するような命令は、プログラムの本来の処理として必要なもの以外は削除される。そのため、ｃｏｒｅ解析時に従来のツールが提供するローカルシンボル参照機能を利用したい場合、一度デバッグ専用のプログラムを同じ条件で走らせ、ｃｏｒｅファイルを再度採取する、という二次的な解析方法を取らなければならなかった。障害発生時の一次調査においては、これらのローカルシンボル参照機能が利用できないため、解析者はローカルシンボルとアドレスの対応を復元するためにｃｏｒｅ出力時に残されたスタックフレームを手作業で解析する必要があった。　この場合、復元可能なローカルシンボルには主に２通りのパターンが存在する。１つはローカルシンボルをスタックフレームに退避する命令が削除されずに残っている場合であり、もう１つはスタックフレームへの退避命令が大域レジスタへ退避命令に置き換わっている場合である。後者の場合は、退避先の大域レジスタの値を復元する必要がある。どちらの場合においても、解析を手作業で行うのは煩雑で困難な作業となる。本発明の目的は、プログラムに障害が発生した時の一次調査において、このようなローカルシンボルが参照するアドレスや退避先の大域レジスタの復元を自動で行うツールを作成し、迅速な障害回復を実現する手段を提供することにある。
【０００４】
【課題を解決するための手段】
ローカルシンボルの退避命令では、ローカルシンボルのアドレスは現行関数のスタックポインタからのオフセットとして扱われる。そのため、ローカルシンボルのアドレスを解決するためには、解析対象関数の実行時のスタックポインタと、アドレスオフセットの２つの値が必要となる。また、大域レジスタは関数の呼び出し先で退避されるレジスタである。そのため、現在解析中の関数における大域レジスタの値を復元するには、スタックフレームを下位（呼び出し先）の方向に辿り、最初に当該大域レジスタを退避している関数を割り出さなければならない。大域レジスタの退避先アドレスも、ローカルシンボルと同様、スタックポインタからのオフセットとして参照される。また、スタックフレーム上の各関数の実行時におけるスタックポインタを復元するためには、障害発生関数からのバックトレースが実行できなければならない。これらの課題を解決するために、本発明ではコンパイラ及びリンカにｃｏｒｅ解析のために必要な情報をオブジェクトモジュールとは別のファイルに出力させる。コンパイラは各関数毎の関数サイズやフレームサイズを格納したテーブル、ローカルシンボルとその退避先を格納したテーブル、レジスタとその退避先を格納したテーブルをそれぞれ出力する。同様に、リンカは関数の先頭アドレスを格納したテーブルを出力する。これらは、コンパイラ及びリンカが従来の処理を行う際に使用する情報をテーブル形式で出力したものである。ｃｏｒｅ解析装置は、これらのテーブル情報をもとにバックトレースの実行やシンボル名解決、大域レジスタ値復元などの解析を実行する。また、デバッガなどのユーザとの対話が可能なソースコード表示装置が、本ｃｏｒｅ解析装置を組み込む際のインターフェース機能を提供する必要がある。これには、外部からの解析要求を識別し、各種解析の実行を制御する手段を備えることで解決する。
【０００５】
【発明の実施の形態】
以下、本発明の実施例を説明する。
【０００６】
図１に本発明の全体構成図を示す。１００は、請求項１に記載したｃｏｒｅ解析装置である。これは、外部との入出力及び全体の制御を行う制御部１０１、バックトレースを実行してバックトレースリストを作成するバックトレース実行部１０２、ローカルシンボル名からアドレスを取得するローカルシンボル解析部１０３、大域レジスタのレジスタ名から値を取得する大域レジスタ値取得部１０４から構成される。１１０は、障害発生時に生成されたｃｏｒｅファイルである。１２０は、ｃｏｒｅ解析装置１００を組み込んだデバッガである。デバッガは、解析コマンド１２１をｃｏｒｅ解析装置へ渡し、解析結果１２２をｃｏｒｅ解析装置から受け取る。１３０は、ｃｏｒｅファイル１１０を発生させたロードモジュールを構成するオブジェクトモジュールを生成したコンパイラである。コンパイラは、各オブジェクトモジュールのコンパイル時に、関数の情報を格納した関数属性テーブル１３１と、ローカルシンボル情報を格納したローカルシンボルテーブル１３２と、レジスタの退避情報を格納した退避レジスタテーブル１３３をファイルに出力する。１４０は、ｃｏｒｅファイル１１０を発生させたロードモジュールを生成したリンカである。リンカは、ロードモジュール生成時に各関数の先頭アドレスを登録した関数アドレステーブル１４１をファイルに出力する。
【０００７】
次に、ｃｏｒｅ解析装置で扱う入出力データの形式を説明する。
【０００８】
図２に解析コマンド１２１の形式を示す。解析コマンドは、コマンドコード２０１、コマンドデータ２０２、関数識別子２０３、スレッド識別子２０４から構成される。コマンドコード２０１は、ｃｏｒｅ解析装置に対する命令を一意に表した内部コードである。図３にコマンドコードの種類を示す。コマンドデータは、「データ取得」３０１、「ローカルシンボル解決」３０２、「大域レジスタ値取得」３０３、「スレッドリスト出力」３０４、「バックトレースリスト出力」３０５、「終了」３０６のいずれかである。コマンドデータ２０２は、コマンドコードの種類に応じてｃｏｒｅ解析装置に渡される解析対象に関するデータである。コマンドコードが「データ取得」の場合、コマンドデータは仮想アドレス空間における絶対アドレスを表す数値である。コマンドコードが「ローカルシンボル解決」の場合、コマンドデータは解析対象変数のローカルシンボル名である。コマンドコードが「大域レジスタ値取得」の場合、コマンドデータは解析対象レジスタのレジスタ番号である。コマンドコードが「スレッドリスト出力」、「バックトレースリスト出力」、「終了」のいずれかの場合、コマンドデータのフィールドは使用されない。関数識別子２０３は、解析対象の関数を一意に表すためのキー情報である。図４に関数識別子の構成を示す。４０１は、解析対象の関数が含まれているモジュールのモジュール名である。４０２は、解析対象の関数名である。４０３は、解析対象の関数が受け取る引数の型を一意に表した関数シグネチャである。コマンドコードが「データ取得」、「スレッドリスト出力」、「バックトレースリスト出力」、「終了」のいずれかの場合、関数識別子のフィールドは使用されない。スレッド識別子２０４は、マルチスレッド環境で出力されたｃｏｒｅファイルに対して、解析対象のスレッドを一意に表す番号である。このフィールドは、コマンドコードが「データ取得」、「スレッドリスト出力」、「終了」のいずれかの場合には使用されない。
【０００９】
解析結果１２２は、解析コマンド１２１に応じてｃｏｒｅ解析装置が解析を行った結果である。解析コマンドが「データ取得」の場合、解析結果は指定されたアドレスに含まれるデータである。解析コマンドが「ローカルシンボル解決」の場合、解析結果は指定されたローカル変数が格納された仮想アドレス空間におけるアドレス値である。解析コマンドが「大域レジスタ値取得」の場合、解析結果は指定されたレジスタのレジスタ値である。解析コマンドが「スレッドリスト出力」の場合、解析結果はｃｏｒｅファイルが出力された時点に存在していたスレッド番号のリストとその要素数である。解析コマンドが「バックトレースリスト出力」の場合、解析結果は指定されたスレッドに対するバックトレースリストとその要素数である。図５にバックトレースリストの構造を示す。バックトレースリスト５００は、関数識別子２０３、スタックポインタ５０１、呼び出し命令アドレス５０２を要素としたリストである。バックトレースリストの１つの要素は１つの関数に対応しており、バックトレースリストのＮ＋１番目の要素に対応する関数はＮ番目の要素に対応する関数を呼び出した関数である。即ち、バックトレースリストの最初の要素はｃｏｒｅファイル出力時に実行していた関数に対応し、バックトレースリストの最後の要素は最上位の関数に対応する。スタックポインタ５０１は、関数識別子２０３が表す関数を実行していた時のスタックポインタの値である。バックトレースリストの最初の要素においては、呼び出し命令アドレス５０２はｃｏｒｅファイル出力時に実行していた命令のアドレスである。バックトレースリストのそれ以外の要素では、呼出し命令アドレスは次の関数を呼び出した命令のアドレスである。
【００１０】
図６に関数属性テーブル１３１の構造を示す。関数属性テーブルは、関数識別子２０３をキーとし、関数サイズ６０１、フレームサイズ６０２を要素とするテーブルである。関数サイズは、関数識別子が表す関数のオブジェクトコード上のサイズを命令単位で表したものである。フレームサイズは、関数識別子が表す関数の関数フレームのサイズをバイト単位で表したものである。
【００１１】
図７にローカルシンボルテーブル１３２のエントリの構造を示す。ローカルシンボルテーブルは、関数識別子２０３とシンボル名７０１の組をキーとし、アドレスオフセット７０２を要素とするテーブルである。アドレスオフセットは、当該シンボルのスタックフレーム上の退避領域のアドレスを表したもので、当該関数のスタックポインタからのバイト単位のオフセットとして表現される。コンパイラの最適化により当該シンボルのスタックフレーム上への退避命令が削除された場合には、当該シンボルに対するローカルシンボルテーブルのエントリは存在しない。
【００１２】
図８に退避レジスタテーブル１３３のエントリの構造を示す。退避レジスタテーブルは、関数識別子２０３とレジスタ番号８０１の組をキーとし、アドレスオフセット８０２を要素とするテーブルである。アドレスオフセットは、当該レジスタのスタックフレーム上の退避領域のアドレスを表したもので、当該関数のスタックポインタからのバイト単位のオフセットとして表される。関数が当該レジスタを退避する必要がないためにスタックフレーム上への退避命令が存在しない場合には、当該レジスタに対する退避レジスタテーブルのエントリは存在しない。
【００１３】
図９に関数アドレステーブル１４１のエントリの構造を示す。関数アドレステーブルは、関数識別子２０３をキーとし、アドレス９０１を要素とするテーブルである。アドレスは、仮想アドレス空間における当該関数の先頭アドレスである。
【００１４】
次に、ｃｏｒｅ解析装置における各部の機能を詳細に説明する。
【００１５】
制御部１０１は、入力した解析コマンド１２１に応じてｃｏｒｅ解析装置の各部の機能を呼び出し、解析結果を外部へ出力する。図１０は制御部の機能を示したフローチャートである。制御部が起動されると、まずバックトレース実行部１０２を呼び出し、バックトレースの実行を行う１００１。次に、解析コマンドの解釈と実行を行うループを実行する。まず、解析コマンドの入力を行い１００２、コマンドコードからコマンドの種類を識別する１００３。もしコマンドコードが「終了」ならば制御部の実行を終了する。それ以外の場合には、コマンドの実行を行う１００４。コマンドの実行１００５では、コマンドコードに応じた処理を実行し、解析結果１２２を取得する。コマンドコードが「データ取得」の場合、コマンドデータに指定されたアドレスをｃｏｒｅファイルから検索し、対応するアドレスを取得する。コマンドコードが「ローカルシンボル解決」の場合、ローカルシンボル解決部１０３を呼び出す。コマンドコードが「大域レジスタ値取得」の場合、大域レジスタ値取得１０４を呼び出す。コマンドコードが「スレッドリスト出力」の場合、バックトレース実行１００１時に得られたスレッドリストを取得する。コマンドコードが「バックトレースリスト出力」の場合、バックトレース実行１００１時に得られたバックトレースリストから、スレッド識別子２０４に指定されたスレッド番号に対応するリストを取得する。最後に、解析結果出力１００６において、コマンドの実行１００５で得られた解析結果１２２を出力する。
【００１６】
バックトレース実行部１０２は、スレッドリストと各スレッドに対するバックトレースリストの作成を行う。図１１はバックトレース実行部の機能を示したフローチャートである。まず、ｃｏｒｅファイルからスレッドを一つ選択し、対応するスレッド番号を取得する１１０１。取得したスレッド番号をスレッドリストへ格納する１１０２。更に、選択したスレッドに対応するスタックポインタ（ＳＰ）と、プログラムカウンタ（ＰＣ）をｃｏｒｅファイルから取得する１１０３。次に、現在のプログラムカウンタからそのアドレスを含む関数を識別する１１０４。これは、関数アドレステーブル１４１から得られる関数アドレス９０１と、関数属性テーブル１３１から得られる関数サイズ６０１を全ての関数識別子２０３に関して検索することで行う。関数アドレスと関数アドレス＋関数サイズに現在のプログラムカウンタが含まれる場合、対応する関数識別子を現行の関数として取得する。関数識別子の取得に失敗した場合には、関数識別子の値は”不明”とする。取得した関数識別子、現在のスタックポインタ及びプログラムカウンタをバックトレースリスト５００へ登録する１１０５。次に、スタックポインタとプログラムカウンタの更新を行う１１０６。更新後のプログラムカウンタは現行関数を呼び出した命令のアドレスである。この値は、スタックポインタから固定長オフセットのアドレスに格納されている関数のリターンアドレスをｃｏｒｅファイルから取得し、その値から１命令分差し引くことで得られる。また、更新後のスタックポインタは、現在のスタックポインタからフレームサイズ６０２分だけ縮めることで得られる。更新後のスタックポインタまたはプログラムカウンタが　ＮＵＬＬ　などの不正な値の場合には、既に最上位関数へ到達したとみなされる。その場合、バックトレース終了の判定処理１１０８へ移行する。更新後のスタックポインタとプログラムカウンタが有効な値である場合には、現行関数の識別処理１１０４へ戻る１１０７。バックトレース終了の判定処理１１０８では、ｃｏｒｅファイルに格納されている全てのスレッドに関して上記の処理を実行したかを判定する。もし全てのスレッドの処理を終えたなら、バックトレース実行部を終了する。そうでない場合、スレッド番号の取得処理１１０１へ戻る。
【００１７】
ローカルシンボル解決部１０３では、指定されたローカルシンボル名からその変数が退避されているスタックポインタ上のアドレスを取得する。図１２はローカルシンボル解決部の機能を示したフローチャートである。まず、解析コマンド１２１で指定された関数識別子２０３及びコマンドデータ２０２として渡されたローカルシンボル名からローカルシンボルテーブル１３２を引き、エントリの有無を確認する１２０１。ローカルシンボルテーブルにエントリが存在しない場合には、当該シンボル名の値はスタックフレーム上に退避されていないため、エラーコードを結果として返す１２０２。ローカルシンボルテーブルのエントリからアドレスオフセット７０２の取得に成功した場合には、その値からアドレス値の計算を行う１２０３。アドレスオフセットは現行関数のスタックポインタからのオフセットであるので、アドレス値の計算にはスタックポインタの値が必要となる。スタックポインタは、バックトレース実行部１０２で作成したバックトレースリストから取得する。まず、解析コマンドで指定されたスレッド識別子に対応するバックトレースリストを取得する。次に、取得したバックトレースリストから解析コマンドで指定された関数識別子が一致する要素を検索し、スタックポインタ５０１を取得する。取得したスタックポインタとアドレスオフセットを加算し、ローカル変数のアドレスを求めて結果として返す１２０４。
【００１８】
大域レジスタ値取得部１０４では、指定された大域レジスタのレジスタ番号からそのレジスタ値を取得する。図１３は大域レジスタ値取得部の機能を示したフローチャートである。まず、解析コマンド１２１のコマンドデータ２０２で指定されたレジスタが当該関数で退避されているかを判定する１３０１。レジスタが退避されている場合には、退避レジスタテーブル１３３にエントリが存在するはずである。退避レジスタテーブルのエントリは、解析コマンドで指定された関数識別子と、コマンドデータに渡されたレジスタ番号が一致するものを検索する。検索の結果取得したアドレスオフセット８０２からレジスタ値を計算して結果として返す１３０２。アドレスオフセットからレジスタ値が格納されているアドレスを取得する方法は、ローカルシンボル解決部での方法１２０３と同様である。計算の結果得られたアドレスをｃｏｒｅファイルから検索することで、当該レジスタ値を取得することができる。退避レジスタテーブルのエントリ検索１３０１に失敗した場合には、次に、当該関数がｃｏｒｅファイルを出力した時点で実行していた関数かどうかを判定する１３０３。この判定は、解析コマンドで指定された関数識別子がバックトレースリストの最初の要素であるかを調べることで行う。もし、当該関数がｃｏｒｅファイルを出力していた時点で実行していた関数ならば、要求されたレジスタ値はその時点でのレジスタ上に存在していたことになる。その場合は、ｃｏｒｅファイルから当該レジスタ値を取得して結果として返す１３０４。そうでない場合には、現在注目しているトレースバックリストの関数識別子が有効かどうかを判定する１３０５。エントリが無効ならばエラーコードを結果として返し１３０６、終了する。エントリが有効ならば、現行関数が呼び出した一つ下位の関数を現行関数とし１３０７、レジスタの退避判定処理１３０１へ戻る。
【００１９】
【発明の効果】
本発明により、プログラムの障害発生時における一次調査において、ローカルシンボルや大域的に使用されるレジスタの値をｃｏｒｅファイルから自動的に復元することが可能となる。
【図面の簡単な説明】
【図１】全体構成図
【図２】解析コマンドの構造
【図３】コマンドデータの種類
【図４】関数識別子の構成要素
【図５】バックトレースリスト
【図６】関数属性テーブル
【図７】ローカルシンボルテーブル
【図８】退避レジスタテーブル
【図９】関数アドレステーブル
【図１０】制御部のフローチャート
【図１１】バックトレース実行部のフローチャート
【図１２】ローカルシンボル解決部のフローチャート
【図１３】大域レジスタ値取得部のフローチャート
【符号の説明】
１００　ｃｏｒｅ解析装置
１０１　制御部
１０２　バックトレース実行部
１０３　ローカルシンボル解決部
１０４　大域レジスタ値取得部
１１０　ｃｏｒｅファイル
１２０　デバッガ
１２１　解析コマンド
１２２　解析結果
１３０　コンパイラ
１３１　関数属性テーブル
１３２　ローカルシンボルテーブル
１３３　退避レジスタテーブル
１４０　リンカ
１４１　関数アドレステーブル
【図１】
2004133827.tif 000003
【図２】
2004133827.tif 000004
【図３】
2004133827.tif 000005
【図４】
2004133827.tif 000006
【図５】
2004133827.tif 000007
【図６】
2004133827.tif 000008
【図７】
2004133827.tif 000009
【図８】
2004133827.tif 000010
【図９】
2004133827.tif 000011
【図１０】
2004133827.tif 000012
【図１１】
2004133827.tif 000013
【図１２】
2004133827.tif 000014
【図１３】
2004133827.tif 000015