JP6061763B2 - 単体試験支援装置及び単体試験支援プログラム - Google Patents

単体試験支援装置及び単体試験支援プログラム Download PDF

Info

Publication number
JP6061763B2
JP6061763B2 JP2013081223A JP2013081223A JP6061763B2 JP 6061763 B2 JP6061763 B2 JP 6061763B2 JP 2013081223 A JP2013081223 A JP 2013081223A JP 2013081223 A JP2013081223 A JP 2013081223A JP 6061763 B2 JP6061763 B2 JP 6061763B2
Authority
JP
Japan
Prior art keywords
function
replaced
address
unit
replacement
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.)
Active
Application number
JP2013081223A
Other languages
English (en)
Other versions
JP2014203384A (ja
Inventor
勝己 奥田
勝己 奥田
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Mitsubishi Electric Corp
Original Assignee
Mitsubishi Electric Corp
Priority date (The priority date 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 date listed.)
Filing date
Publication date
Application filed by Mitsubishi Electric Corp filed Critical Mitsubishi Electric Corp
Priority to JP2013081223A priority Critical patent/JP6061763B2/ja
Publication of JP2014203384A publication Critical patent/JP2014203384A/ja
Application granted granted Critical
Publication of JP6061763B2 publication Critical patent/JP6061763B2/ja
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Landscapes

  • Debugging And Monitoring (AREA)

Description

この発明は、ソフトウェアの単体試験を行うための単体試験支援装置およびそのプログラムに関するものである。
ソフトウェア技術者は、ソフトウェアの単体試験において、試験対象プログラムを関数単位で試験をする場合がある。一般に、単体試験は、試験対象関数と試験ドライバと試験スタブとから構成される。試験ドライバは、試験の事前条件を設定し、試験対象関数を呼び出し、事後条件を確認する。試験スタブは、試験対象関数が呼び出す別の関数のダミーである。試験時のソフトウェア構成として試験対象関数が使用する関数をダミーの試験スタブに置き換えることで、試験対象関数の実行フローを制御しやすくなる。この結果、ソフトウェア技術者は、試験を効率化に進めることができる。
一般に、関数のダミースタブによる置換は、被置換関数の定義を含むオブジェクトファイルの代わりに、ダミースタブの定義を含むオブジェクトファイルを試験ドライバや試験対象関数を含むファイルとリンクすることによって行われる。従って、試験対象関数と試験スタブによる被置換候補の関数とが同一ソースファイルに記述されている場合は、被置換候補の関数を試験スタブで置き換えるのは困難である。
このため、試験スタブを用いた試験を行うソフトウェア開発では、ソフトウェアの構成として不自然であっても被置換候補の関数を試験対象プログラムとは別のソースファイル中で記述したり、試験時のみプリプロセッサディレクティブなどで被置換候補の関数をコンパイル対象から除外するなどの工夫が必要であった。結果として、試験スタブを利用することで、場合によってはソフトウェアの保守性が悪くなるなどの問題があった。
このような問題を解決するためには、被置換対象の関数が試験対象プログラムと同じファイルで定義されている場合でも、ソースコードを変更せずにプログラムの挙動を変更する仕組みが必要となる。そのような仕組みを提供する方法としてコードを変換する方法があった(例えば特許文献1)。
特開2009−237610号公報
しかしながら、従来の方法では、試験ドライバでの試験記述とは別に、関数フックの条件を記述する必要があった。このため、試験ケースを作成するためにソフトウェア技術者が複数のファイルを編集する必要があり、作業が煩雑であるという問題があった。
この発明は、上記のような問題点を解決するためになされたものであり、ソフトウェアの単体試験における作業を簡略化することのできる単体試験支援装置を得ることを目的とする。
この発明に係る単体試験支援装置は、試験対象プログラム中で書き換えられる被置換関数の識別子と、被置換関数を書き換えるための置換関数の識別子を入力する関数置換部と、被置換関数の識別子から試験対象プログラムの書換え位置のアドレスを取得するアドレス解決部と、アドレス解決部が取得したアドレスの試験対象プログラムを書き換えることで被置換関数を置換関数で書き換えるプログラム書換え部とを備えたものである。
この発明の単体試験支援装置は、被置換関数の識別子から試験対象プログラムの書換え位置のアドレスを取得し、このアドレスの試験対象プログラムを書き換えることで被置換関数を置換関数で書き換えるようにしたので、ソフトウェアの単体試験における作業を簡略化することができる。
この発明の実施の形態1による単体試験支援装置を示す構成図である。 この発明の実施の形態1による単体試験支援装置の試験ドライバの動作を示すフローチャートである。 この発明の実施の形態1による単体試験支援装置の関数置換前の関数呼出しを模式的に示す説明図である。 この発明の実施の形態1による単体試験支援装置の関数先頭書換えによる関数置換後の関数呼出しを模式的に示す説明図である。 この発明の実施の形態1による単体試験支援装置の関数先頭書換えによる試験支援部の処理を示すフローチャートである。 この発明の実施の形態1による単体試験支援装置のオブジェクトファイル読出し処理の詳細を示すフローチャートである。 この発明の実施の形態1による単体試験支援装置のステップST502の関数先頭アドレス取得処理の詳細を示すフローチャートである。 この発明の実施の形態1による単体試験支援装置のシンボル検索処理の詳細を示すフローチャートである。 この発明の実施の形態2による単体試験支援装置の関数先頭アドレス取得処理を示すフローチャートである。 この発明の実施の形態3による単体試験支援装置の関数先頭アドレス取得処理を示すフローチャートである。 この発明の実施の形態4による単体試験支援装置の関数先頭アドレス取得を模式的に示す説明図である。 この発明の実施の形態4による単体試験支援装置の関数先頭アドレス取得処理を示すフローチャートである。 この発明の実施の形態4による単体試験支援装置のセクション先頭アドレス取得を模式的に示す説明図である。 この発明の実施の形態4による単体試験支援装置のセクション先頭アドレス取得処理を示すフローチャートである。 この発明の実施の形態5による単体試験支援装置の試験支援部の処理を示すフローチャートである。 この発明の実施の形態6による単体試験支援装置の関数置換前の共有ライブラリ関数呼出しを模式的に示す説明図である。 この発明の実施の形態6による単体試験支援装置の関数置換後の共有ライブラリ関数呼出しを模式的に示す説明図である。 この発明の実施の形態6による単体試験支援装置の試験支援部の処理を示すフローチャートである。 この発明の実施の形態6による単体試験支援装置の関数アドレス参照書換え処理を示すフローチャートである。 この発明の実施の形態7による単体試験支援装置の関数置換処理を示すフローチャートである。 この発明の実施の形態8による単体試験支援装置を示す構成図である。 この発明の実施の形態9による単体試験支援装置を示す構成図である。
実施の形態1.
図1は、この発明の実施の形態1による単体試験支援装置を示す構成図である。
図1に示す単体試験支援装置は、試験設定部100、試験対象プログラム110、試験支援部120、言語処理部130を備えている。この単体試験支援装置は、試験対象プログラム110中の試験対象関数111の単体試験を想定している。単体試験の目的は、試験対象関数111が仕様通りに実装されていることを確認することである。
試験設定部100は、試験ドライバ101と置換関数(試験スタブ)102とを含んでいる。試験設定部100は、試験記述プログラムを計算機が実行することで実現されている。この試験記述プログラムは1つ以上のソースプログラムから構成されているものとする。
試験時には、試験対象プログラム110が本来利用する被置換関数112を試験スタブである置換関数102で置き換えて試験対象関数111を実行する。試験対象関数111の呼出しを行うのが、試験ドライバ101である。また、試験ドライバ101は、試験支援部120の関数置換部121を呼び出すことで、実行時に被置換関数112を置換関数102に置き換える機能を有している。
試験対象プログラム110は、試験対象となるプログラムであり、試験対象関数111は、試験対象プログラム110における単体試験の対象となる関数である。また、被置換関数112は、試験対象関数111からcallされ、置換関数102で置換される関数である。
試験支援部120は、試験ドライバ101によって呼び出され、試験対象プログラム110における被置換関数112を置換関数102に置き換える処理を行うものであり、関数置換部121、アドレス解決部122、プログラム書換え部123を備えている。関数置換部121は、被置換関数112の識別子と置換関数102の識別子とを入力し、これらの入力に基づいてアドレス解決部122とプログラム書換え部123とを実行させる機能を有している。アドレス解決部122は、被置換関数112の識別子からプログラムの書換え位置のアドレスを取得する処理部である。プログラム書換え部123は、アドレス解決部122が取得したアドレスのプログラムを書き換えることで被置換関数112を置換関数102で置き換える処理部である。
言語処理部130は、試験設定部100が用いる試験記述プログラムと、試験対象プログラム110と、試験支援部120における置換え結果と、必要なライブラリとから試験を行うための実行可能ファイルを作成する処理部であり、試験プログラム140は、その実行可能ファイルである。
なお、試験設定部100および試験支援部120におけるそれぞれの機能部と言語処理部130は、それぞれの機能を実現するためのプログラムと、これらのプログラムを実行するためのCPUやメモリといったハードウェアによって構成され、コンピュータを用いて実現されている。また、これらのプログラムは、ソースコードやリロケータブルなオブジェクトファイル、静的ライブラリ、共有ライブラリなどの形式で記憶媒体に格納可能である。
次に、試験設定部100における試験ドライバ101について説明する。試験ドライバ101の主な処理は、試験対象関数111の実行に必要な事前条件を設定した後、試験対象関数111を呼び出し、呼出し後の事後条件を確認することである。
図2に、試験ドライバ101の処理フローを示す。
試験ドライバ101は、ステップST201で試験対象関数が実行の前提とする事前条件を設定する。具体的には、試験対象関数111が利用する入力変数の初期化などを行う。ステップST202は、試験対象関数111が利用する関数を置換関数102に置き換える処理である。試験ドライバ101は、試験支援部120が提供する関数置換部121を呼び出すことで、試験支援部120が、被置換関数112を置換関数102に置き換える。本実施の形態では、試験対象プログラム110自身の識別子と被置換関数112の識別子と置換関数102の識別子とを関数置換部121への入力とする。以下の説明では、具体的に試験対象プログラム110自身の識別子として試験対象プログラム110のファイル名、被置換関数112の識別子として被置換関数の名前、置換関数102の識別子として置換関数のアドレスを使用するが、識別子の形式をこれに限定するものではない点に注意が必要である。なお、置換関数102のアドレスは、C/C++言語によって構成されている試験ドライバ101の場合、アドレス参照の演算子である&で取得可能な値である。
ステップST203では、試験対象関数111の呼出しを行う。このとき試験ドライバ101は、後で試験対象関数111の戻り値があれば記憶する。
ステップST204は、試験対象関数111が期待通りに動作したか否かを確認する処理である。事後条件として試験対象関数111が変更した値やステップST203で記憶した試験対象関数の戻り値などを確認する。一般的なxUNITなどの試験フレームワークを用いる場合、事後条件の確認には、試験ドライバ101は、フレームワークが提供するアサーションなどを利用する。
次に、関数置換処理について説明する。
始めに、図3と図4とを用いて、試験対象関数111における関数置換前後の関数呼出しの様子を説明した後、関数置換処理の説明を行う。
図3は、関数置換前の関数呼出しの模式図である。試験対象関数301と被置換関数302とは、計算機の主記憶上に格納されたプログラムである。これら試験対象関数301と被置換関数302は、図1の試験対象関数111と被置換関数112に対応している。試験対象関数301は、被置換関数302への呼出し命令CALLを含んでいる。計算機が被置換関数302への呼出し命令を実行すると、計算機のプログラムカウンタは、被置換関数302のアドレスに移る。計算機は、被置換関数302を実行し、被置換関数302の関数復帰命令retを実行すると試験対象関数301に制御が移動する。
図4は、本実施の形態における関数先頭書換えによる関数置換後の関数呼出しの模式図である。図4では、図3に加えて主記憶上の置換関数403も記載している。ここで、試験対象関数401と被置換関数402および置換関数403は、図1の試験対象関数111と被置換関数112及び置換関数102に対応している。
図3と異なるのは、被置換関数402の先頭部分である。被置換関数402の先頭部分の命令は、置換関数403への無条件分岐命令JMP命令に書き換わっている。計算機は、試験対象関数401の被置換関数402への呼出し命令CALLを実行すると、プログラムカウンタは、被置換関数402の先頭アドレスとなる。先頭には置換関数403への無条件分岐命令が存在するため、計算機の制御は直ちに置換関数403の先頭に移る。置換関数403中で関数復帰命令retが実行されると、制御は試験対象関数401中の被置換関数402呼出し命令の直後の命令に移る。
次に、図3の関数呼出しを図4の関数呼出しに変更するための関数置換処理について図5を用いて説明する。
図5は、関数先頭書換えによる図1の試験支援部120の処理フローである。なお、図1のアドレス解決部122の処理がステップST502に対応し、プログラム書換え部123の処理がステップST503に対応する。
関数置換処理の入力は、試験対象プログラム110のファイル名、被置換関数112の名前、置換関数102のアドレスである。本処理の概要は、入力となる試験対象プログラム110の実行可能ファイルを解析し、プログラム書換え箇所のアドレスを解決し、当該箇所のプログラムを書き換えることである。本実施の形態では、プログラム書換え箇所は被置換関数112の先頭アドレスである。また、被置換関数112の先頭アドレスの取得を試験対象プログラム110のシンボル情報から行う。以下の説明では、シンボル情報として試験対象プログラム110の実行可能ファイルに含まれるシンボルテーブルを想定するが、シンボルテーブルの代わりに言語処理系が生成するMAPファイルを用いても同様の結果を得ることができる。
ステップST501は、後で被置換関数112の先頭アドレスを取得するために必要なシンボルテーブルなどの情報を主記憶上にロードする処理である。本処理の詳細は図6を用いて後述する。なお、本実施の形態の説明では、オブジェクトファイルの情報を一括してステップST501で主記憶上にロードするものとしたが、情報を用いるときにその都度ファイルにアクセスするようにしてもよい。
ステップST502は、被置換関数112の名前を入力とし、ステップST502で読み出したシンボルテーブルから被置換関数112の先頭アドレスを取得する処理である。本処理の詳細については図7を用いて後述する。
ステップST503では、ステップST502で取得した被置換関数の先頭アドレスの命令を置換関数への無条件分岐命令に書き換える。具体例として、単体試験をAMD64アーキテクチャのCPUの計算機上で行う場合、無条件分岐命令は、オペコードが0xE9のJMP命令である。当該JMP命令は、プログラムカウンタ相対ジャンプ命令である。ここでは、ジャンプ命令のオペランドに、(置換関数のアドレス)−(関数の先頭アドレス)−(JMP命令の命令バイト長)を設定する。なお、JMP命令の命令バイト長の値は5である。
このように、プログラム書換え部123の処理であるステップST503において、関数の先頭アドレスのコードを置換関数に無条件分岐する命令に書き換えることによって、試験対象プログラム110が被置換関数112を呼び出すと、結果的に置換関数が実行される効果を得ることができる。
以下では、ステップST501のオブジェクトファイル読出し処理と、ステップST502の関数先頭アドレス取得処理について説明する。具体的にオブジェクトファイルのフォーマットとしては、ELF(Executable and Linkable Format)を想定して説明するが、Windows PE(Windowsは登録商標/以下省略して記載)やMach−Oなどの異なるオブジェクトファイルフォーマットでも本発明は同様に適用可能である。
図6は、図5におけるオブジェクトファイル読出し処理の詳細を示すフローチャートであり、ここでは、ELFファイルの読出し処理を示している。ELFファイルの読出し処理フローでは、ELFファイルの名前を入力として、ELFファイルの解析に必要となる情報をメモリ上に読み出す。ここで読み出す情報は、本実施の形態では特に図5のステップST502で関数先頭アドレス取得に必要となるシンボルテーブルである。
ステップST601は、ELFファイル名のファイルのオープン処理である。このとき、ファイルのオープンには、ELFファイル読出し処理の入力として与えられるファイル名を用いる。オープンしたファイルはクローズする必要があるが、クローズ処理については本発明とは直接関係しないため、クローズ処理の説明は、以後、省略するものとする。
ステップST602では、ELFファイルの先頭に格納されたファイルヘッダを読み出す処理である。ファイルヘッダは、後の処理で利用するセクションヘッダテーブルのオフセットとセクションヘッダの個数などを保持している。
ステップST603は、セクションヘッダテーブルを読み出す処理である。ステップST602で読み出したELFヘッダに含まれるセクションヘッダテーブルの位置と個数を参照し、ELFファイル中の当該位置からセクションデータテーブルをメモリに読み出す。このとき、セクションヘッダテーブルの位置は、ファイルヘッダのe_shoffフィールドに格納されている。また、セクションヘッダの個数はe_shnumに格納されている。
ステップST604は、セクションヘッダ用の文字列テーブルをファイルからメモリに読み出す処理である。まず、ステップST602で読み出したファイルヘッダのe_shstrndxフィールドの値を用いて、ステップST603で読み出したセクションヘッダテーブルの先頭から数えてe_shstrndx番目のセクションヘッダから、セクションヘッダ用文字列テーブルのファイル中でのオフセットとサイズを取得する。セクションヘッダ用文字列テーブルのオフセットとサイズとは、それぞれセクションヘッダのsh_offsetフィールドとsh_sizeフィールドとから取得可能である。
ステップST605は、文字列テーブルを読み出す処理である。ELFファイルでは、文字列テーブルは、名前が.strtabのセクションに格納されている。まず、セクションヘッダテーブルから名前が.strtabのセクション名を取得する。セクションヘッダの名前は、セクションヘッダのsh_nameフィールドの値を用いて取得可能である。具体的には、セクションヘッダ用の文字列テーブル先頭からsh_nameフィールドバイト目に存在するゼロ終端文字列がセクションヘッダ名である。
ステップST606は、シンボルテーブルを読み出す処理である。シンボルテーブルは、名前が.symtabのセクションである。ステップST605における文字列テーブルの場合と同様に.symtabをセクションヘッダテーブルから検索し、セクションヘッダに記載された位置からシンボルテーブルをメモリに読み出す。このとき、シンボルの位置とサイズとは、それぞれセクションヘッダのsh_offsetフィールドとsh_sizeフィールドの値である。なおsh_sizeの値とシンボルテーブルエントリの商は、シンボルテーブルのエントリ数となる。ステップST606では、エントリ数もメモリに記憶しておく。
ステップST607は、リロケーションテーブルを読み出す処理である。リロケーションテーブルは、リロケーション対象となるセクションごとに存在する。また、各々のリロケーションテーブルも、独立したセクションに格納されている。リロケーションテーブルが格納されているセクションは、.relまたは.relaに続ききリロケーション対象となるセクション名で始まる名前を持つセクションに格納されている。例えば、.textセクションのリロケーションテーブルであれば、.rel.textまたは.rela.textを名前に持つセクションに格納されている。ステップST607では、.relまたは.relaのセクションをメモリ上にロードする。
次に、図7を用いてステップST502の関数先頭アドレス取得処理の詳細を説明する。図7は、実行可能ファイルシンボル情報による関数先頭アドレス取得処理のフローである。本処理では、被置換関数112の名前を入力とし、ステップST501で読み出したシンボルテーブルから被置換関数112の名前と一致するシンボルを検索することで、被置換関数112のアドレスを取得する。
ステップST701では、被置換関数112の名前をシンボル名とするシンボルテーブルエントリを検索する処理である。シンボル検索処理の詳細は、図8を用いて後述する。ここでは、シンボルテーブル検索処理への入力とする検索条件として、シンボルの名前が被置換関数112の名前と一致することを指定する。なお、シンボル名は、シンボルテーブルエントリのst_nameフィールドの値を文字列テーブルのインデックスとして読み出せるゼロ終端文字列から得られる。シンボル検索処理からは、検索条件に合致するシンボルの一覧が得られる。
ステップST702は、ステップST701で検索したシンボルがシンボルテーブル中に見つかったか否かに基づく条件分岐処理である。シンボルが見つかったか否かは、ステップST701で得られるシンボル一覧が空でないか否かで判定可能である。シンボルが見つからなかった場合、エラーで終了する。一方、シンボルが見つかっている場合、ステップST703に分岐する。
ステップST703は、ステップST701で検索したシンボルがシンボルテーブル中に2つ以上見つかったか否かに基づく条件分岐処理である。シンボルが2つ以上みつかった場合は、エラーで終了する。一方、見つかったシンボルが1つのみである場合、ステップST704に分岐する。
ステップST704では、見つかったシンボルの値、すなわち被置換関数112のアドレスを主力結果に格納する。シンボルの値は、ステップST701で検索の結果として唯一の得られたシンボルテーブルエントリのst_valueフィールドの値である。
このように、アドレス解決部122の処理であるステップST502が、被置換関数112の名前を用いて試験対象プログラム110の実行可能ファイルのシンボル情報を検索することで、被置換関数112の先頭アドレスを取得できるため、試験対象プログラム110がデバッグ情報を保持していなくても被置換関数112の先頭アドレスを取得することができる効果を得ることができる。
次に、ステップST701のシンボル検索処理について図8を用いて説明する。
シンボル検索処理は、シンボルテーブルエントリを巡回し、入力とする検索条件と一致するを持つシンボルテーブルエントリの一覧を返す処理である。ステップST801は、検索結果をクリアする処理である。ステップST802〜ST805は、シンボルテーブルエントリを巡回するループ処理である。すなわち、ステップST803でシンボルが検索条件と一致するかを判定し、一致した場合はステップST804で検索結果にシンボルテーブルエントリを追加し、一致しなかった場合はそのまま次のシンボルテーブルエントリに進む。シンボルテーブルエントリ数は、図6のELFファイル読出し処理のステップST606処理時に記憶した値を参照することで得られる。
このように、実施の形態1では、関数置換部121を試験ドライバ101から呼び出せるようにすることで、試験ドライバ101の処理中で被置換関数112を置換関数102で置き換えることができる。また、アドレス解決部122を設けることで、プログラム書換え対象となるアドレスを試験対象プログラム110の実行時に取得できることができる。また、プログラム書換え部123を設けることで、試験ドライバ101の実行時に被置換関数112の呼出しを置換関数102の呼出しとすることができる。
以上説明したように、実施の形態1の単体試験支援装置によれば、試験対象プログラム中で書き換えられる被置換関数の識別子と、被置換関数を書き換えるための置換関数の識別子を入力する関数置換部と、被置換関数の識別子から試験対象プログラムの書換え位置のアドレスを取得するアドレス解決部と、アドレス解決部が取得したアドレスの試験対象プログラムを書き換えることで被置換関数を置換関数で書き換えるプログラム書換え部とを備えたので、ソフトウェアの単体試験における作業を簡略化することができる。
また、実施の形態1の単体試験支援装置によれば、アドレス解決部は、被置換関数の識別子から試験対象プログラムの書換え位置のアドレスとして被置換関数の先頭アドレスを取得し、プログラム書換え部は、先頭アドレスからのメモリ内容を置換関数に直接または間接的に分岐する1つ以上の命令に書き換えるようにしたので、試験対象プログラムが被置換関数を呼び出すと結果的に置換関数が実行されることを容易に実現することができる。
また、実施の形態1の単体試験支援装置によれば、アドレス解決部は、被置換関数の識別子を用いて試験対象プログラムのシンボル情報を検索することで、被置換関数の先頭アドレスを取得するようにしたので、試験対象プログラムがデバッグ情報を備えていなくても被置換関数の先頭アドレスを取得することができる。
また、実施の形態1の単体試験支援プログラムによれば、ソフトウェアの単体試験を行うためのコンピュータを、試験対象プログラム中で書き換えられる被置換関数の識別子と、被置換関数を書き換えるための置換関数の識別子を入力する関数置換部と、被置換関数の識別子から試験対象プログラムの書換え位置のアドレスを取得するアドレス解決部と、アドレス解決部が取得したアドレスの試験対象プログラムを書き換えることで被置換関数を置換関数で書き換えるプログラム書換え部として機能させるようにしたので、ソフトウェアの単体試験における作業を簡略化することができる単体試験支援装置をコンピュータ上に実現することができる。
実施の形態2.
実施の形態1では、試験対象プログラム110のソースファイル群のうち、複数のソースファイルで同一名のローカル関数が定義されている場合、シンボルテーブルには、同一のシンボル名を持つエントリが複数存在する。このような場合は、被置換関数112の先頭アドレスを正しく解決できないことが問題となる。具体的には、図7のステップST703でシンボルが複数見つかるため、エラーとなる。このような問題を解決するのが実施の形態2である。なお、図面上の構成は図1と同様であるため、図1の構成を用いて説明する。
本実施の形態では、試験ドライバ101から被置換関数112が定義されているソースファイルを関数置換部121に伝達することで、シンボル解決が曖昧になることを回避することが基本的な仕組みである。このようにすることで、1つのソースファイルで同名の関数が複数定義されることはないため、ソースファイルと関数名で試験対象プログラム110に含まれる被置換関数112を一意に識別することができる。すなわち、実施の形態2では、アドレス解決部122が、被置換関数112の名前と被置換関数112を含むソースファイルの識別子を用いて試験対象プログラム110のデバッグ情報を検索することで、被置換関数112の先頭アドレスを取得するよう構成されている。その他の構成は実施の形態1と同様である。
以下、本実施の形態の動作説明として実施の形態1との差分を説明する。
まず、実施の形態2では、図5のステップST502の関数先頭アドレス取得処理が、シンボル情報ではなく、試験対象プログラム110のデバッグ情報を用いる点と、被置換関数112を含むソースファイルの名前を余分に入力とする点とが実施の形態1と異なる。また、関数置換部121への入力として、被置換関数112を含むソースファイル識別子が入力に加わる。同様に、図2のステップST202では、入力にソースファイル識別子が入力として加わる。
以下の説明では、識別子としてソースファイル名を用いるものとするが、最終的にソースファイル名に変換可能であれば任意の識別子で代用可能である。例えば、一般にオブジェクトファイル名とソースファイル名との相違は拡張子の部分だけであることを利用すると、オブジェクトファイル名やそのベースファイル名を識別子としても容易にソースファイル名を得ることができる。
次に、本実施の形態における、図5のステップST502の関数先頭アドレス取得処理を、図9を用いて説明する。
図9は、デバッグ情報による関数先頭アドレス取得処理のフローである。処理の入力は、被置換関数112の名前と被置換関数112を含むソースファイルの名前である。
ステップST901では、関数置換処理の入力の試験対象プログラム110に含まれるデバッグ情報から、ソース名と被置換関数名をキーとして被置換関数112のアドレスを取得する。本処理において、デバッグ情報からソース名と関数名の対で関数のアドレスを取得する処理は公知であるため、ここでは処理の概要のみを示す。デバッグ情報がDWARF形式の場合、デバッグ情報は、.debug_infoセクションに格納されている。ステップST901では、はじめにタグがDW_TAG_compilation_unitであるDIEの中から属性DW_AT_nameがソースファイル名と一致するDIE検索する。次に当該DIEの後続DIEのうちタグがDW_TAG_subprogramの中からDW_AT_nameが関数名と一致するDIEを検索する。結果として見つかったDIEの属性DW_AT_low_pcの値が求める関数先頭アドレスである。
ステップST902は、ステップST901の結果に基づく条件分岐処理である。ステップST901で被置換関数112のアドレスを取得することができなかった場合、エラー終了する。一方、ステップST901でアドレスを取得できた場合、ステップST903に分岐する。ステップST903では、ステップST901で取得した被置換関数112の値を結果として出力する。
以上説明したように、実施の形態2の単体試験支援装置によれば、アドレス解決部は、被置換関数の名前と被置換関数を含むソースファイルの識別子を用いて試験対象プログラムのデバッグ情報を検索することで、被置換関数の先頭アドレスを取得するようにしたので、試験対象プログラム中に被置換関数と同じ名前を持つ関数が複数存在する場合であっても、被置換関数を一意に取得することができる。
実施の形態3.
実施の形態2では、被置換関数112が定義されているファイル名を用いて被置換関数112の先頭アドレスを取得した。このため、被置換関数112を定義しているソースファイルを変更した場合は、正しく試験が実行できないことになる。具体的には、被置換関数112を定義しているソースファイルが変更された場合、図9のステップST902において、被置換関数112の情報が見つからないため、エラー終了する。従って、被置換関数112を定義しているソースファイルが変更された後も正しく試験を実行するためには、試験ドライバ101側の修正も必要となる。具体的には、図2のステップST202の入力の被置換関数112を含むソースファイル識別子を更新する必要がある。ソースファイルが変更される例としては、試験対象関数111と同じソースファイルに定義されていた被置換関数112が、リファクタリングなどで別のソースファイルに移動される場合などが挙げられる。
このような問題を解決するのが、本実施の形態である。すなわち、被置換関数112が定義されているファイルが変更されても、試験ドライバ101側の変更を不要とする。以下では実施の形態2との差分で本実施の形態を説明する。なお、図面上の構成は図1と同様である。
本実施の形態が実施の形態2とは異なる点は、関数置換部121の入力として被置換関数112のソースファイル識別子ではなく、試験対象関数111のソースファイル識別子を用いる点である。すなわち、実施の形態3のアドレス解決部122は、被置換関数112の名前と、試験対象関数111のソースプログラム識別子とを用いて被置換関数112の先頭アドレスを取得し、見つからなければ被置換関数112の名前のみを用いて被置換関数112の先頭アドレスを検索するよう構成されている。その他の構成は実施の形態1と同様である。
以降の説明では、ソースファイル識別子としてソースファイル名を用いることを想定して説明する。
図5のステップST502の関数先頭アドレス取得処理の入力は、被置換関数112を含むソースファイルの名前ではなく、試験対象関数111のソースファイル識別子である。また、関数置換部121への入力も同様に、被置換関数112を含むソースファイル識別子ではなく、試験対象関数111のソースファイル識別子である。同様に、図2のステップST202では、試験対象関数111のソースファイル識別子を入力とする。
次に、本実施の形態における、図5のステップST502の関数先頭アドレス取得処理を、図10を用いて説明する。
図10は、ソースファイル名を用いた関数先頭アドレス取得処理を示すフローチャートである。処理の入力は、被置換関数112の名前と、試験対象関数111を含むソースファイルの名前である。
ステップST1001では、試験対象関数111を含むソースファイルの名前と被置換関数112の名前とで関数のアドレスを検索する。具体的には、試験対象関数111のソースファイルに定義されている関数の中から被置換関数112の名前を持つ関数のアドレスを取得する。この処理は実施の形態2におけるステップST901と概ね同じである。
ステップST1002では、ステップST1001の処理結果に基づく分岐処理である。ステップST1001で被置換関数112の情報が見つかった場合、ステップST1003に分岐する。それ以外の場合は、ステップST1004に分岐する。
ステップST1003では、ステップST1001で見つかった被置換関数の情報から先頭アドレスを取得し、処理の結果として出力する。
ステップST1004では、関数名が被置換関数と一致するグローバル関数を検索する処理である。この処理は公知であるため、ここでは処理の概要のみを示す。具体的にデバッグ情報がDWARF形式の場合、タグがDW_TAG_subprogramのDIEの中から、属性DW_AT_nameが被置換関数の名前と一致しており、かつ属性DW_AT_externalが1のDIEを検索すればよい。見つかったDIEの属性DW_AT_low_pcの値が求めるアドレスである。
ステップST1005は、ステップST1004の結果に基づく分岐処理である。ステップST1004で被置換関数112の情報が見つかった場合、ステップST1006に分岐する。それ以外の場合、エラー終了する。
ステップST1006は、ステップST1004で見つかった被置換関数112の情報から先頭アドレスを取得し、処理の結果として出力する。
このように、アドレス解決部122の処理であるステップST502の実現手段として、関数アドレス取得処理において、被置換関数112の名前とソースプログラム識別子とを用いて被置換関数112の先頭アドレスを取得し(ステップST1001)、見つからなければ被置換関数112の名前のみを用いて被置換関数112の先頭アドレスを検索する(ステップST1004)手段を持つことで、被置換関数112が定義されているファイルの位置に依存することなく、被置換関数112を置換関数102で置き換えることができる。このため、試験ドライバ101作成後に、被置換関数112が別のファイルに移動された場合においても、試験ドライバ101を修正する必要がなくなるという効果を得ることができる。
なお、上記説明では、試験対象関数111のソースプログラム識別子をソースプログラムのファイル名として説明したが、試験対象関数111の名前や試験対象関数111のアドレスで代用することも可能である。試験対象プログラム110のデバッグ情報を検索すれば、試験対象関数111の名前や試験対象関数111のアドレスから試験対象関数111を定義しているソースプログラムを特定することができるためである。
また、試験対象関数111のソースプログラム識別子としてファイル名ではなく試験対象関数111のアドレスを用いることで、試験対象関数111のソースファイルの名前が変更されても試験ドライバ101を変更する必要がなくなるという効果を新たに得ることもできる。
以上説明したように、アドレス解決部は、被置換関数の名前と、試験対象プログラムが実行される場合に被置換関数を呼び出す試験対象関数のソースプログラム識別子とを用いて被置換関数の先頭アドレスを取得し、見つからなければ被置換関数の名前のみを用いて被置換関数の先頭アドレスを検索するようにしたので、被置換関数が定義されているファイルの位置に依存することなく、被置換関数を置換関数で置き換えることができる。このため、試験ドライバ作成後に、被置換関数が別のファイルに移動された場合においても、試験ドライバを修正する必要がないという効果が得られる。
実施の形態4.
実施の形態2、3では、被置換関数112のアドレスを取得するためにデバッグ情報を用いた。このため、被置換関数112を含むオブジェクトファイル自体がデバッグ情報を保持する必要がある。そのためには、被置換関数112を定義するソースファイルのコンパイル時にデバッグ情報の出力オプションがコンパイラに指定されている必要がある。従って、被置換関数112を含むオブジェクトファイルのソースコードが得られない場合などに、実施の形態2は適用できないことになる。本実施の形態では、この問題を解決する方法を提供する。なお、本実施の形態においても、図面上の構成は図1と同様である。
本実施の形態では、図10のステップST1001とステップST1004でデバッグ情報を用いた関数の先頭アドレス取得処理の代わりにシンボル情報を用いた関数先頭アドレス取得処理を行うことを特徴とする。すなわち、実施の形態4のアドレス解決部122は、被置換関数112の名前と、試験対象プログラム110が実行される場合に被置換関数112を呼び出す試験対象関数111のリロケータブルファイルとを用いて被置換関数112の先頭アドレスを取得し、見つからなければ被置換関数112の名前のみを用いて被置換関数112の先頭アドレスを検索するよう構成されている。
次に、実施の形態4の単体試験支援装置の動作について説明する。
始めに、処理が単純なステップST1004のシンボル情報を用いた関数先頭アドレス取得処理を説明する。ステップST1004では、グローバルな被置換関数112のアドレスを取得することが目的である。そこで、本実施の形態では、ステップST501で読み出した試験対象プログラム110のシンボルテーブルから、被置換関数112の名前と一致しかつグローバルなシンボルのエントリを取得すればよい。シンボル検索処理は実施の形態1で示した通りである。なお、シンボルがグローバルであるか否かは、シンボルテーブルエントリのst_infoの上位4ビットがSTB_GLOBALか否かで判定可能である。また、シンボルが関数か否かは、シンボルテーブルエントリのst_infoフィールドの下位4ビットがSTT_FUNCか否かで判定可能である。
次に、図11と図12を用いてステップST1001に対応する処理について説明する。
図11は、リロケータブルファイルのシンボル情報による関数先頭アドレス取得の模式図である。アドレス空間1101は、試験対象プログラム110を含むプロセスのアドレス空間である。また、リロケータブルファイル1103は、試験対象関数111を含むリロケータブルファイルである。リロケータブルファイル1103は、コードを含む.textセクション1105を保持している。また、.textセクション1105の中に図1の被置換関数112に対応する被置換関数1106が存在するものとする。.textセクション1105は、アドレス空間1101においては、セクション先頭アドレスB1102の位置にマップされている。また、リロケータブルファイル1103は、リロケータブルファイルシンボルテーブル1104も含んでいる。リロケータブルファイルシンボルテーブル1104は、被置換関数1106に対応するエントリをもつ。当該シンボルテーブルエントリには、被置換関数の.textセクション1105からのオフセットAが値として記憶されている。本実施の形態では、計算機が(セクション先頭アドレスB)+(オフセットA)を計算することで、ロケータブルファイルのシンボル情報による関数先頭アドレス取得処理を実現する。
図12は、リロケータブルファイルのシンボル情報による関数先頭アドレス取得処理を示すフローチャートである。
ステップST1201は、被置換関数1106を含むリロケータブルファイル名を入力としてオブジェクトファイル読出し処理を行う。オブジェクトファイル読出し処理は、実施の形態1で示した通りである。リロケータブルファイル1103の名前は、ソースファイル名の拡張子を変更して得られる。例えば、C言語のソースファイルであれば、拡張子を.cから.oや.objに変更すればよい。
ステップST1202では、被置換関数名のシンボルをステップST1201で読み出したシンボルテーブルから検索する処理である。シンボル検索処理は実施の形態1で示した通りである。ここでは、シンボル検索処理の入力に与える検索条件は、シンボルの名前が被置換関数1106の名前と一致することである。シンボルテーブルエントリのシンボル名は、シンボルテーブルエントリのst_nameフィールドを、ステップST1201で読み出した文字列テーブルのインデックスとして読み出せるゼロ終端文字列である。
ステップST1202で得られるシンボルテーブルエントリのst_valueフィールドは、関数が定義されているセクションの先頭からのオフセットである。なお、ここでは説明を単純化するため関数が定義されているセクションが標準的な.textセクションであると想定して説明するが、別のセクションであってもよい。その場合は、シンボルが存在するセクションをステップST1202で記憶し、ステップST1205の処理では記憶したセクションを対象として先頭アドレスを取得すればよい。シンボルテーブルエントリのst_shndxフィールドの参照で行うことで、シンボルが存在するセクションを特定することができる。
ステップST1203では、ステップST1202の処理結果に基づく条件分岐処理である。ステップST1202でシンボルが見つからなかった場合、エラーとして終了する。一方、ステップST1202で条件と一致するシンボルが見つかった場合はステップST1204に分岐する。
ステップST1204では、見つかったシンボルの値を変数Aに格納する。次に、ステップST1205では、ステップST1201で読み出したリロケータブルファイル1103における.textセクション1105のアドレス空間1101における先頭アドレスを取得する処理である。ステップST1205の詳細については図13と図14とを用いて後述する。
ステップST1206では、ステップST1205で取得したセクション先頭アドレスをBに格納する。また、ステップST1207では、A+Bの計算によって関数先頭アドレスを計算し、結果として出力する。
次に、図12におけるステップST1205のセクション先頭アドレス取得処理について図13と図14とを用いて説明する。
図13は、セクション先頭アドレス取得の模式図である。アドレス空間1301は、試験対象プログラム110のプロセスのアドレス空間である。リロケータブルファイル1303は、試験対象プログラム110を含むリロケータブルファイルであり、.textセクション1304とリロケータブルファイルシンボルテーブル1306を含む。また、.textセクション1304には任意のグローバル関数G1305が1つ含まれるものとする。リロケータブルファイルシンボルテーブル1306は、グローバル関数G1305に対応するエントリを保持している。当該エントリは、グローバル関数G1305の.textセクション1304からのオフセットXを保持している。また、実行可能ファイルシンボルテーブル1307は、試験対象プログラム110の実行可能ファイルのシンボルテーブルである。実行可能ファイルシンボルテーブル1307も、グローバル関数G1305に対応するエントリを保持している。当該エントリは、アドレス空間1301におけるグローバル関数G1305のアドレスYを保持している。本実施の形態では、ステップST1205におけるセクション先頭アドレス取得処理が、(グローバル関数G1305のアドレスY)−(グローバル関数G1305のセクション先頭1からのオフセットX)を計算することでテキスト先頭アドレスを求める。
図14は、セクション先頭アドレス取得処理を示すフローチャートである。セクション先頭アドレス取得処理の入力は、実行可能ファイルの名前と本処理の呼出し元で読み出したリロケータブルの情報とである。
ステップST1401は、ステップST1201で読み出したリロケータブルファイルからグローバルな関数のシンボルを取得する処理である。シンボル検索処理は、実施の形態1で説明した通りであるが、検索条件としては、シンボルがグローバルな関数であることを指定する。シンボルがグローバルか否かはシンボルテーブルエントリのst_infoの上位4ビットがSTB_GLOBALか否かで判定可能である。また、シンボルが関数か否かは、シンボルテーブルエントリのst_infoフィールドの下位4ビットがSTT_FUNCか否かで判定可能である。
ステップST1402は、ステップST1401の結果に基づく条件分岐処理である。ステップST1401でシンボルが見つからなかった場合、エラー終了する。一方、シンボルが見つかった場合、ステップST1403に分岐する。ステップST1403では、ステップST1401で得られたシンボル一覧の先頭を変数Xに代入する処理である。ここではシンボル一覧の先頭を選択したが、実際にはシンボルがグローバルの関数である条件を満足する任意のシンボルをXに代入してよい。
ステップST1404では、実行可能ファイル名を入力としてオブジェクトファイル読出し処理を行う。オブジェクトファイル読出し処理の詳細は、実施の形態1で説明した通りである。なお、ステップST501でも同じ情報を読み出しているため、その情報をそのまま用いることで本処理を省略することも可能である。
ステップST1405では、ステップST1404で読み出したファイル情報からシンボルを検索する処理である。このとき、検索条件として、ステップST1403で代入したシンボルXの名前と一致することを指定する。
ステップST1406は、ステップST1405の結果に基づく条件分岐処理である。ステップST1405でシンボルが見つからなかった場合はエラー終了する。一方、シンボルが見つかった場合はステップST1407に分岐する。
ステップST1407では、ステップST1406の結果で得られたシンボル一覧の先頭を変数Yに代入する処理である。ステップST1405では、グローバルな関数のシンボルXの名前で検索しているため、通常結果として得られる一覧は、1つのシンボルのみ含む。
ステップST1408では、Y−Xを計算することでセクション先頭アドレスを計算する。シンボルの値は、具体的にはXとYとそれぞれのst_valueフィールドの値である。Yのシンボル値は、グローバル関数の先頭アドレスであり、Xのシンボル値は、セクション先頭からのオフセットである。両者の差をとることで、セクション先頭のアドレスを取得することができる。
以上説明したように、実施の形態4の単体試験支援装置によれば、アドレス解決部は、被置換関数の名前と、試験対象プログラムが実行される場合に被置換関数を呼び出す試験対象関数のリロケータブルファイルとを用いて被置換関数の先頭アドレスを取得し、見つからなければ被置換関数の名前のみを用いて被置換関数の先頭アドレスを検索するようにしたので、被置換関数が定義されているファイルの位置に依存することなく、被置換関数を置換関数で置き換えることができる。このため、試験ドライバ作成後に、被置換関数が別のファイルに移動された場合においても、試験ドライバを修正する必要がなくなるという効果を得ることができる。
また、実施の形態4の単体試験支援装置によれば、アドレス解決部は、被置換関数の定義を含むリロケータブルファイルのシンボル情報と試験プログラムのシンボル情報とセクション先頭アドレスとから、被置換関数の先頭アドレスを算出するようにしたので、デバッグ情報を用いることなく試験対象関数と同じファイルで定義された被置換関数のアドレスを取得することができる。このとき、被置換関数がローカル関数で、同名のローカル関数が試験プログラムに複数含まれていても被置換関数のアドレスを一意に特定することができる。被置換関数がローカル関数の場合、試験対象関数が呼び出す被置換関数は、必ず被置換関数と同じソースファイルで唯一定義されているためである。
実施の形態5.
実施の形態1〜4では、それぞれアドレス解決部122は異なる関数先頭アドレスの取得手段を用いて先頭アドレスの取得を行った。具体的には、実施の形態1では、図7に示した実行可能ファイルのシンボル情報を用いた関数先頭アドレス取得手段を用いた。また、実施の形態2では、図9に示したデバッグ情報による関数先頭アドレス取得手段を用いた。また、実施の形態3では、図10のソースファイル名を用いた関数先頭アドレス取得手段としてデバッグ情報を用いて実現する手段を示した。また、実施の形態4では、図10のソースファイル名を用いた関数先頭アドレス取得手段としてリロケータブルファイルのシンボル情報を用いて実現する手段について示した。このように、アドレス解決部122における関数先頭アドレス取得手段は複数存在する。それぞれの関数先頭アドレス取得手段は、シンボル情報やデバッグ情報など異なる情報を用いて被置換関数112のアドレスを取得する。このため、試験ドライバ作成者は、利用可能な情報を元に適切な関数先頭アドレス取得手段を選択する必要があるという問題があった。上記問題を解決するのが本実施の形態である。
本実施の形態では、複数の関数先頭アドレス取得手段の試行手段を備えたアドレス解決部122を持つことを特徴とする。すなわち、実施の形態5のアドレス解決部122は、試験対象プログラム110のデバッグ情報の有無、または、試験対象関数111のリロケータブルファイルの有無に基づいて、被置換関数112の先頭アドレスを取得する手段を選択するよう構成されている。
本実施の形態における試験支援部120の処理フローを図15に示す。
関数置換部121の入力は、試験対象関数111のソースファイル名、試験対象プログラム110の実行可能ファイル名、被置換関数112の名前である。
ステップST1501は、試験対象プログラム110の実行可能ファイルの情報を読み出す処理である。本処理は、ステップST501と同じである。ステップST1502は、デバッグ情報があるか否に基づく分岐処理である。デバッグ情報が存在する場合はステップST1505に分岐し、それ以外の場合は、ステップST1504に分岐する。デバッグ情報があるか否かは、ステップST1501で読み出したセクションヘッダテーブルを検索し、デバッグ情報を含むセクションの存在有無を確認することで行うことができる。例えば、実行可能ファイルのフォーマットがELF形式でデバッグ情報のフォーマットがDWARFである場合、.debug_infoセクションがあればデバッグ情報が存在するとみなし、なければ存在しないとみなせばよい。
ステップST1503は、デバッグ情報を用いた関数先頭アドレス取得処理である。本処理は、実施の形態3における図10の処理と同じである。
ステップST1504は、試験対象関数111のソースファイルに対応するリロケータブルファイルの有無による条件分岐処理である。リロケータブルファイルの有無確認は、ソースファイル名から取得したリロケータブルファイル名がファイルシステム上に存在するか否かで行うことができる。リロケータブルファイルが存在すればステップST1505に分岐し、それ以外の場合はステップST1506に分岐する。
ステップST1505は、リロケータブルファイルのシンボル情報を用いた関数先頭アドレス取得処理である。本処理は、実施の形態4の説明に基づく図10の処理と同じである。
ステップST1506は、実行可能ファイルシンボル情報による関数先頭アドレス取得処理である。本処理は、実施の形態1の図7の処理と同じである。
ステップST1507は、ステップST1503、またはステップST1505またはステップST1506で取得した関数先頭アドレスに置換関数102への無条件分岐命令を書き込む処理である。本処理の詳細は実施の形態1で示した通りである。
以上説明したように、実施の形態5の単体試験支援装置によれば、アドレス解決部は、試験対象プログラムのデバッグ情報の有無、または、試験対象関数のリロケータブルファイルの有無に基づいて、被置換関数の先頭アドレスを取得する手段を選択するようにしたので、試験ドライバ作成者は、被置換関数の先頭アドレスを取得する手段が利用可能な情報試験ドライバを作成するといったことがなく、試験ドライバ作成者の負担を軽減することができる。
実施の形態6.
実施の形態1では、被置換関数自体を書き換えることで関数置換処理を実現している。しかし、被置換関数が共有ライブラリ関数の場合には置換できないことが問題となる。一般に、共有ライブラリは複数のプロセスから共有されるため、共有ライブラリ関数が書き換わると試験対象プログラム110以外のプログラムにも影響を及ぼすことになる。そこで、被置換関数112が共有ライブラリ関数の場合の関数置換処理を実現するのが本実施の形態である。
本実施の形態におけるアドレス解決部122は、試験対象プログラム110のアドレス空間において被置換関数112を参照している箇所のアドレスを取得し、プログラム書換え部123は、アドレス解決部122が取得したアドレスの箇所を置換関数102のアドレス参照に書き換えるよう構成されている。その他の構成は図1に示した実施の形態1と同様である。
始めに、図16と図17とを用いて、試験対象関数111における関数置換前後の関数呼出しの様子を説明した後、関数置換処理の説明を行う。
図16は、関数置換前の共有ライブラリ関数呼出しの模式図である。ここでは、具体的にオブジェクトファイルの形式がELFの場合の共有ライブラリ関数呼出しの様子を示すが、Windows PEやMach−oも類似のトランポリンコードを用いた共有ライブラリ関数呼出しとなるため、本発明を適用することが可能である。なお、ここではダイナミックリンクが完了している状態を示す。
試験対象関数1601と被置換関数1604とPLT1602とGOT.PLT1603は、計算機の主記憶上に格納されたプログラムおよびデータである。なお、試験対象関数1601と被置換関数1604は、図1における試験対象関数111と被置換関数112に対応するプログラムである。試験対象関数1601は、共有ライブラリの被置換関数呼出し時には、被置換関数1604を直接呼び出す代わりに被置換関数1604に対応するPLT(Procedure Linkage Table)のエントリPLT[n]を呼び出す。当該PLTのエントリPLT[N]は、被置換関数1604に対応するGOT.PLT1603のエントリに格納されたアドレスにジャンプする。GOT.PLT1603のエントリGOT[N]が被置換関数1604のアドレスを含んでいる。この結果、PLTエントリPLT[N]のジャンプ命令を介して被置換関数1604が呼び出される。被置換関数1604中で関数復帰命令RETが実行されると、試験対象関数1601の被置換関数1604呼出し命令の直後の命令に処理制御が移る。
図17は、関数置換後の共有ライブラリ関数呼出しの模式図である。なお、図17において、試験対象関数1701、被置換関数1704および置換関数1705は、それぞれ図1における試験対象関数111、被置換関数112および置換関数102に対応するプログラムである。置換関数1705は主記憶に格納された置換関数である。GOT.PLT1703の被置換関数1704に対応するエントリGOT[N]が被置換関数1704のアドレスではなく、置換関数1705のアドレスを保持する。この結果、試験対象関数1701がPLT1702のエントリPLT[N]を呼び出すと、GOT.PLT[N]が保持する置換関数1705のアドレスに間接ジャンプする。その結果、処理制御は置換関数1705の先頭に移る。置換関数1705中で関数復帰命令RETが実行されると、処理制御は、試験対象関数1701の被置換関数1704呼出しの直後の命令に移る。
次に、図16の共有ライブラリ関数呼出しを図17の共有ライブラリ関数呼出しに変更する関数置換処理を図18を用いて説明する。
図18は、共有ライブラリ関数用の試験支援部120の処理フローである。ステップST1801では、試験対象プログラム110のファイル名を入力としてオブジェクトファイルを読み出す。本処理の詳細は、実施の形態1に示したので省略する。
ステップST1802は、関数アドレス参照書換え処理である。関数アドレス参照処理への入力としてGOT.PLT用のダイナミックリロケーションテーブルを渡す。ELFファイルの場合、.rela.pltまたは.rel.pltが関数アドレス参照処理への入力とするリロケーションテーブルを保持している。
次に、ステップST1802の関数アドレス参照書換え処理の詳細を図19のフローチャートを用いて説明する。
関数アドレス参照書換え処理では、リロケーション情報を利用することで、.GOT.PLT中の被置換関数112のエントリを、被置換関数112のアドレスから置換関数102のアドレスに書き換える。
図19に示す関数アドレス参照書換え処理では、被置換関数112の名前と.textセクション先頭アドレスと置換関数102のアドレスとを入力とする。また、関数アドレス参照書換え処理では、ステップST1901で読出した.textセクションのリロケーションテーブルも利用する。
ステップST1901からステップST1905は、ステップST1901で読み出したセクションのリロケーションテーブルのエントリを巡回するループ処理である。
ステップST1902は、巡回中のリロケーションテーブルエントリの対象が被置換関数112か否かに基づく条件分岐処理である。巡回エントリの対象が被置換関数112でない場合、ステップST1903とステップST1904をスキップする。一方、巡回中のエントリが被置換関数112に対応する場合ステップST1903に分岐する。
巡回中のエントリが被置換関数112に対応するか否かは、リロケーションテーブルエントリがリンクしているシンボルテーブルエントリの名前が被置換関数112の名前と一致しているか否かで確認可能である。リロケーションテーブルエントリがリンクしているシンボルは、リロケーションテーブルエントリのr_infoフィールドを参照することで取得可能である。r_infoフィールドからシンボルテーブルインデックスを取得し、ステップST1901で読み出したシンボルテーブルにアクセスすることで目的とするシンボルを得ることができる。さらにシンボルテーブルエントリのst_nameフィールドから文字列テーブルのインデックスを読出し、ステップST1901で読み出した文字列テーブルにアクセスすることでシンボルの名前を取得できる。
ステップST1903は、被置換関数の参照箇所のアドレスを取得する処理である。ここでは、被置換関数の呼出し箇所のアドレスをリロケーションテーブルエントリのオフセットから取得する。具体的には、リロケーションテーブルエントリのオフセットは、r_offsetフィールドの値である。この値は、図16のGOT.PLT1603のエントリGOT[N]のアドレスである。
ステップST1904は、ステップST1903で取得した被置換関数参照箇所のアドレスに存在するデータを置換関数102のアドレスに書き換える処理である。この結果として図17のようにGOT.PLT1703のエントリGOT[N]は、置換関数1705のアドレスを保持するようになる。
以上説明したように、実施の形態6の単体試験支援装置によれば、アドレス解決部は、試験プログラムのアドレス空間において被置換関数を参照している箇所のアドレスを取得し、プログラム書換え部は、アドレス解決部が取得したアドレスの箇所を置換関数のアドレス参照に書き換えるようにしたので、被置換関数が共有ライブラリ中の関数である場合にも被置換関数を置換関数に置き換えることができる。
実施の形態7.
実施の形態6では、被置換関数112が共有ライブラリの場合の関数置換処理を示した。しかし、このような場合、試験ドライバ作成者は、被置換関数112が共有ライブラリ関数か否かで試験ドライバ101の仕様に対応した関数置換処理を選択する必要がある。そこで、本実施の形態では、被置換関数112が共有ライブラリ関数か否かに関わらず関数を置換することができる関数置換処理について示す。即ち、実施の形態7におけるアドレス解決部122は、被置換関数112が共有ライブラリか否かを判定し、共有ライブラリであった場合に実施の形態6の処理を行い、かつ、プログラム書換え部も実施の形態6の処理を行うよう構成されている。その他の構成は図1に示した実施の形態1と同様である。
本実施の形態による関数置換処理を図20のフローチャートに示す。
ステップST2001では、試験対象プログラム110のオブジェクトファイル情報を読み出す処理である。本処理の詳細は実施の形態1の説明で示した通りである。
ステップST2002は、被置換関数112が共有ライブラリ関数か否かに基づく分岐処理である。被置換関数112が共有ライブラリ関数であれば、ステップST2003に分岐し、それ以外の場合はステップST2004に分岐する。被置換関数112が共有ライブラリ関数か否かは、GOT.PLT用のダイナミックリロケーションテーブルエントリを探索し、被置換関数112に対応するエントリの有無で判定可能である。被置換関数112に対応するエントリが見つかった場合、被置換関数112は共有ライブラリ関数である。
ステップST2003は、関数アドレス参照書換え処理である。本処理は、実施の形態6の図19の処理と同様であるため、ここでの説明は省略する。
ステップST2004は、関数先頭アドレス取得処理である。関数先頭アドレスの取得手段は任意であり、実施の形態1〜5で示した関数先頭アドレス取得処理などを利用すればよい。
ステップST2005では、ステップST2004で取得した関数先頭アドレスのコードを置換関数102への無条件分岐命令に書き換える。本処理の詳細は実施の形態1に示した通りである。
以上説明したように、実施の形態7の単体試験支援装置によれば、アドレス解決部は、被置換関数が共有ライブラリか否かを判定し、共有ライブラリであった場合にアドレスの取得を行い、かつ、プログラム書換え部によるアドレスの書換えを行うようにしたので、試験ドライバ作成者は、被置換関数が共有ライブラリか否かで関数置換処理を選択することなく、試験ドライバを作成することができる。また、被置換関数が後で共有ライブラリ関数に変更された場合であっても試験ドライバを修正する必要がなくなる。
実施の形態8.
実施の形態1〜7では、実行中の試験プログラム自体を動的に書き換えることで、被置換関数を置換関数に置き換えた。このため、関数置換処理を呼び出す試験ドライバの実行後に別の試験ドライバを呼び出すと、別の試験ドライバが期待通りに動作しない場合があることが問題となる。そこで、本実施の形態では、置換した関数を元に戻す手段を実施の形態1〜7に加えるようにしたものである。
本実施の形態の全体構成図を図21に示す。本構成では、実施の形態1〜7のいずれかの構成に加えて関数置換復元部124が存在する。本実施の形態におけるプログラム書換え部123は、被置換関数112を置換関数102で置き換えた場合、置き換えたアドレスとサイズと置き換え前のデータの組を置き換え履歴として記憶するよう構成されている。また、関数置換復元部124は、記憶した置き換え履歴に基づいて、関数置換を復元する処理部である。その他の構成は図1と同様であるため、対応する部分に同一符号を付してその説明を省略する。
本実施の形態において、置換した関数の復元は、プログラム書換え部123と関数置換復元部124とが協調して動作することで実現される。具体的には関数置換処理では、処理中でプログラムを書き換えると同時に、書き換えたアドレスと書き換えたサイズと書換え前のデータとからなる組を置換履歴としてメモリ上に記憶する。さらに関数置換処理では、関数置換処理実行中においてメモリ上に記憶した置換履歴の識別子を出力する。例として、置換履歴一覧の識別子には、置換換履歴一覧を記憶したメモリのアドレスを用いればよい。
なお、置換履歴を記憶するタイミングを具体的に記述すると、図5におけるステップST503、図15におけるステップ1507、図19におけるステップST1904、図20におけるステップST2005である。
次に関数置換復元部124の動作について示す。関数置換復元部124は、プログラム書換え部123が出力した置換履歴識別子を入力とし、対応する置換履歴に格納されたアドレスに対して書換え前のデータを書き換えたデータのサイズ分だけ書き戻すことで、関数置換を復元する。
以上説明したように、実施の形態8の単体試験支援装置によれば、被置換関数を置換関数で置き換えた場合、置き換えたアドレスとサイズと置き換え前のデータの組を置き換え履歴として記憶すると共に、記憶した置き換え履歴に基づいて、関数置換を復元する関数置換復元部を備えたので、関数置換処理を行った場合でも、試験対象プログラム全体に関数置換処理による影響が及ぶことを防ぐことができる。
実施の形態9.
実施の形態1では、ジャンプコード挿入処理においてメモリ上の関数アドレスをジャンプコードに入れ換えることで関数の置換を行った。しかし、Linux(Linuxは登録商標/以下省略して記載)などのオペレーティングシステムでは、セキュリティ対策などのため、コード領域への書き込みが禁止されている場合が多い。したがって、Linuxのようにコード領域への書込みを禁止しているオペレーティングシステム上では、実施の形態1のジャンプコード挿入処理において、メモリアクセス違反が発生してしまう。この問題を解決するのが本実施の形態である。
本実施の形態の単体試験支援装置の全体構成図を図22に示す。
本実施の形態では、試験支援部120bとして、実施の形態1〜8のいずれかの構成に加えてメモリ解除部125が加わっていることが特徴である。なお、図22では、実施の形態1〜7の構成に対してメモリ解除部125を付加した構成を示している。メモリ解除部125は、プログラム書換え部123によるプログラム書換え処理の前にメモリ保護解除処理を行う処理部である。他の構成は、実施の形態1〜8のいずれかと同様であるため、ここでの説明は省略する。
本実施の形態において、メモリ解除部125は、プログラム書換え部123における被置換関数112の置換関数102での書換え処理の前にメモリ解除処理を実行し、書換え対象領域のメモリ保護を解除する。このメモリ解除処理を実行するタイミングとしては、具体的には図5におけるステップST503を実行する直前などが該当するが、書換え前であれば、どのタイミングであってもよい。
メモリ解除処理の具体的な例として、Linuxの場合のメモリ保護解除処理を以下に示す。Linuxの場合、メモリ保護解除をmprotectシステムコールを用いて行う。mprotectの第一引数のアドレスは、シンボルアドレスを含むページの先頭アドレスである必要がある。ページ先頭アドレスは、シンボルアドレスの下位12ビットの値をゼロとすることで求めえられる。mprotectの第二引数は、権限を設定する対象領域のサイズである。シンボルアドレス+シンボルサイズーページ先頭アドレスをmprotectの第二引数とする。mprotectの第3引数は、プロテクションの属性である。ここでは、読出し/書込み/実行の権限を与えるために、PROT_READ | PROT_WRITE |PROT_EXECを与える。ここで、|は、ビットごとの論理和演算を意味する。また、PROT_READ, PROT_WRITE,PROT_EXECは、読出し、書込み、実行の権限を与えることを意味する。
以上説明したように、実施の形態9の単体試験支援装置によれば、プログラム書換え部によるプログラム書換え処理の前にメモリ保護解除処理を行うメモリ解除部を備えたので、コード領域にメモリ保護をかけているオペレーティングシステム上で被置換関数を置換関数に置き換えることができる。
なお、本願発明はその発明の範囲内において、各実施の形態の自由な組み合わせ、あるいは各実施の形態の任意の構成要素の変形、もしくは各実施の形態において任意の構成要素の省略が可能である。
100 試験設定部、101 試験ドライバ、102 置換関数、110 試験対象プログラム、111 試験対象関数、112 被置換関数、120,120a,120b 試験支援部、121 関数置換部、122 アドレス解決部、123 プログラム書換え部、124 関数置換復元部、125 メモリ解除部、130 言語処理部、140 試験プログラム。

Claims (13)

  1. 試験対象プログラム中で書き換えられる被置換関数の識別子と、前記被置換関数を書き換えるための置換関数の識別子を入力する関数置換部と、
    前記被置換関数の識別子から前記試験対象プログラムの書換え位置のアドレスを取得するアドレス解決部と、
    前記アドレス解決部が取得したアドレスの前記試験対象プログラムを書き換えることで前記被置換関数を前記置換関数で書き換えるプログラム書換え部とを備えた単体試験支援装置。
  2. 前記アドレス解決部は、前記被置換関数の識別子から前記試験対象プログラムの書換え位置のアドレスとして当該被置換関数の先頭アドレスを取得し、
    前記プログラム書換え部は、前記先頭アドレスからのメモリ内容を前記置換関数に直接または間接的に分岐する1つ以上の命令に書き換えることを特徴とする請求項1記載の単体試験支援装置。
  3. 前記アドレス解決部は、前記被置換関数の識別子を用いて前記試験対象プログラムのシンボル情報を検索することで、前記被置換関数の先頭アドレスを取得することを特徴とする請求項2記載の単体試験支援装置。
  4. 前記アドレス解決部は、前記被置換関数の名前と当該被置換関数を含むソースファイルの識別子を用いて前記試験対象プログラムのデバッグ情報を検索することで、前記被置換関数の先頭アドレスを取得することを特徴とする請求項2の単体試験支援装置。
  5. 前記アドレス解決部は、前記被置換関数の名前と、前記試験対象プログラムが実行される場合に前記被置換関数を呼び出す試験対象関数のソースプログラム識別子とを用いて前記被置換関数の先頭アドレスを取得し、見つからなければ前記被置換関数の名前のみを用いて当該被置換関数の先頭アドレスを検索することを特徴とする請求項2記載の単体試験支援装置。
  6. 前記アドレス解決部は、前記被置換関数の名前と、前記試験対象プログラムが実行される場合に前記被置換関数を呼び出す試験対象関数のリロケータブルファイルとを用いて前記被置換関数の先頭アドレスを取得し、見つからなければ前記被置換関数の名前のみを用いて当該被置換関数の先頭アドレスを検索することを特徴とする請求項2記載の単体試験支援装置。
  7. 前記アドレス解決部は、前記被置換関数の定義を含むリロケータブルファイルのシンボル情報と前記試験対象プログラムのシンボル情報とセクション先頭アドレスとから、前記被置換関数の先頭アドレスを算出することを特徴とする請求項2記載の単体試験支援装置。
  8. 前記アドレス解決部は、前記試験対象プログラムのデバッグ情報の有無、または、前記試験対象プログラムが実行される場合に前記被置換関数を呼び出す試験対象関数のリロケータブルファイルの有無に基づいて、前記被置換関数の先頭アドレスを取得する手段を選択することを特徴とする請求項1記載の単体試験支援装置。
  9. 前記アドレス解決部は、前記試験対象プログラムのアドレス空間において前記被置換関数を参照している箇所のアドレスを取得し、
    前記プログラム書換え部は、前記アドレス解決部が取得したアドレスの箇所を前記置換関数のアドレス参照に書き換えることを特徴とする請求項1記載の単体試験支援装置。
  10. 前記アドレス解決部は、前記被置換関数が共有ライブラリか否かを判定し、当該共有ライブラリであった場合に前記アドレスの取得を行い、かつ、前記プログラム書換え部による前記アドレスの書換えを行うことを特徴とする請求項9記載の単体試験支援装置。
  11. 前記被置換関数を前記置換関数で置き換えた場合、置き換えたアドレスとサイズと置き換え前のデータの組を置き換え履歴として記憶すると共に、
    前記記憶した置き換え履歴に基づいて、関数置換を復元する関数置換復元部を備えたことを特徴とする請求項1記載の単体試験支援装置。
  12. プログラム書換え部によるプログラム書換え処理の前にメモリ保護解除処理を行うメモリ解除部を備えたことを特徴とする請求項1記載の単体試験支援装置。
  13. ソフトウェアの単体試験を行うためのコンピュータを、
    試験対象プログラム中で書き換えられる被置換関数の識別子と、前記被置換関数を書き換えるための置換関数の識別子を入力する関数置換部と、
    前記被置換関数の識別子から前記試験対象プログラムの書換え位置のアドレスを取得するアドレス解決部と、
    前記アドレス解決部が取得したアドレスの前記試験対象プログラムを書き換えることで前記被置換関数を前記置換関数で書き換えるプログラム書換え部として機能させるための単体試験支援プログラム。
JP2013081223A 2013-04-09 2013-04-09 単体試験支援装置及び単体試験支援プログラム Active JP6061763B2 (ja)

Priority Applications (1)

Application Number Priority Date Filing Date Title
JP2013081223A JP6061763B2 (ja) 2013-04-09 2013-04-09 単体試験支援装置及び単体試験支援プログラム

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
JP2013081223A JP6061763B2 (ja) 2013-04-09 2013-04-09 単体試験支援装置及び単体試験支援プログラム

Publications (2)

Publication Number Publication Date
JP2014203384A JP2014203384A (ja) 2014-10-27
JP6061763B2 true JP6061763B2 (ja) 2017-01-18

Family

ID=52353742

Family Applications (1)

Application Number Title Priority Date Filing Date
JP2013081223A Active JP6061763B2 (ja) 2013-04-09 2013-04-09 単体試験支援装置及び単体試験支援プログラム

Country Status (1)

Country Link
JP (1) JP6061763B2 (ja)

Family Cites Families (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH07319683A (ja) * 1994-05-30 1995-12-08 Nippon Telegr & Teleph Corp <Ntt> 運用中プログラム更新方式
JP2008123438A (ja) * 2006-11-15 2008-05-29 Fujitsu Ltd コンピュータシステム、プログラム情報収集方法、およびコンピュータプログラム
JP4931711B2 (ja) * 2007-07-02 2012-05-16 日本電信電話株式会社 カーネル更新方法、情報処理装置、プログラムおよび記憶媒体
JP5550578B2 (ja) * 2011-02-06 2014-07-16 三菱電機株式会社 エントリ書換装置及びエントリ書換プログラム

Also Published As

Publication number Publication date
JP2014203384A (ja) 2014-10-27

Similar Documents

Publication Publication Date Title
Williams-King et al. Egalito: Layout-agnostic binary recompilation
ElWazeer et al. Scalable variable and data type detection in a binary rewriter
US9134966B2 (en) Management of mixed programming languages for a simulation environment
CN107451474B (zh) 用于终端的软件漏洞修复方法和装置
US20080127113A1 (en) Method and system for implementing watchpoints
JP7042270B2 (ja) セルフデバッギング
US10795659B1 (en) System and method for live patching processes in user space
Stüttgen et al. Robust Linux memory acquisition with minimal target impact
US11693760B2 (en) System and methods for live debugging of transformed binaries
US20230267067A1 (en) Software protection from attacks using self-debugging techniques
US9047403B2 (en) Debugger with previous version feature
US20110029953A1 (en) System and Method for Scalable Handling of Debug Information
JP2008052688A (ja) プログラムのパッチデータ生成装置
Heitman et al. BARF: a multiplatform open source binary analysis and reverse engineering framework
JP6061763B2 (ja) 単体試験支援装置及び単体試験支援プログラム
JP5550578B2 (ja) エントリ書換装置及びエントリ書換プログラム
JP2011090511A (ja) 実行プログラム、コンパイラ、実行プログラム動作修正装置及び実行プログラム動作修正方法
KR102684371B1 (ko) 셀프 디버깅
JP2007041777A (ja) 言語処理方法
Yin et al. PAST: accurate instrumentation on fully optimized program
Ghafari Detecting Variadic Functions in Stripped Binaries from C/C++
JP5109808B2 (ja) 追加実行可能情報生成装置、情報処理装置、及びプログラム
HELLEBRANDT Vyhledávání výrazů s nedefinovaným chováním v jazyce C
Nguyen et al. Simulating Loader for Mach-O Binary Obfuscation and Hooking
Fahem et al. Efficient Conditional Tracepoints in Kernel Space

Legal Events

Date Code Title Description
A621 Written request for application examination

Free format text: JAPANESE INTERMEDIATE CODE: A621

Effective date: 20151015

A977 Report on retrieval

Free format text: JAPANESE INTERMEDIATE CODE: A971007

Effective date: 20160729

A131 Notification of reasons for refusal

Free format text: JAPANESE INTERMEDIATE CODE: A131

Effective date: 20160809

A521 Request for written amendment filed

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20160923

TRDD Decision of grant or rejection written
A01 Written decision to grant a patent or to grant a registration (utility model)

Free format text: JAPANESE INTERMEDIATE CODE: A01

Effective date: 20161115

A61 First payment of annual fees (during grant procedure)

Free format text: JAPANESE INTERMEDIATE CODE: A61

Effective date: 20161213

R150 Certificate of patent or registration of utility model

Ref document number: 6061763

Country of ref document: JP

Free format text: JAPANESE INTERMEDIATE CODE: R150

R250 Receipt of annual fees

Free format text: JAPANESE INTERMEDIATE CODE: R250

R250 Receipt of annual fees

Free format text: JAPANESE INTERMEDIATE CODE: R250

R250 Receipt of annual fees

Free format text: JAPANESE INTERMEDIATE CODE: R250

R250 Receipt of annual fees

Free format text: JAPANESE INTERMEDIATE CODE: R250

R250 Receipt of annual fees

Free format text: JAPANESE INTERMEDIATE CODE: R250