次に、本発明の実施の形態について図面を参照して説明する。図1は本発明の第1の実施の形態によるプログラムデバッグ装置の構成例を示すブロック図である。図1には、本発明の第1の実施の形態によるプログラムデバッグ装置において、T個のアドレス値を得るための手段の構成の一例を示している。尚、このプログラムデバッグ装置は、プログラムを作成したり、変換したりする情報処理装置、あるいはプログラムを実行して各種処理を行う情報処理装置等に搭載可能である。
図1において、本発明の第1の実施の形態によるプログラムデバッグ装置1は、第1プログラム変換実行・メモリアクセストレース部11−1、第2プログラム変換実行・メモリアクセストレース部11−2、・・・、第Tプログラム変換実行・メモリアクセストレース部11−T(以下、メモリアクセストレース部11−1〜11−Tとする)と、メモリセグメントアドレス割当部(以下、アドレス割当部)12と、データ解析部13と、を備えている。尚、図1に示す構成は、あくまでも一つの構成例を示すものであって、これと同様に、複数のアドレス値が得られる実施形態であれば、異なる構成であっても構わない。
本実施形態のプログラムデバッグ装置1は、プログラムの実行時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスをデバッグすることができ、特に当該プログラムの実行に伴ってなされるメモリアクセスを解析して境界判定を行うことができる。
上記プログラムを格納する記憶領域は、プログラムデバッグ装置1に接続される外部の記憶装置であってもよいし、プログラムデバッグ装置1に備えられる記憶装置であってもよい。
アドレス割当部12は、記憶領域のアドレスのうちセグメントが割り当てられるアドレスのみを変更してセグメントの配置を変更することができる。
メモリアクセストレース部11−1〜11−Tは、アドレス割当部12にてセグメントの配置を変更されたプログラムを実行するとともにプログラムの実行に伴ってなされるメモリアクセスをトレースして、メモリアクセスにより参照された参照先アドレスを得るとともに、プログラムが実行された結果を示す実行結果、メモリアクセスがなされた回数を示すアクセス回数またはプログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得ることができる。
データ解析部13は、アドレス割当部12とメモリアクセストレース部11−1〜11−Tとによりプログラムを複数回実行して、得られた複数の実行結果、アクセス回数または実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析部131と、実行結果解析部131にて実行された全ての回において等しいと判定されたとき、複数の実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析部132と、を含むことができる。
上述したように、不連続に行われるメモリアクセスに対しても、確実な境界判定を行うためには、個々のメモリアクセスに対して、アクセス先のアドレスを計算する際の基点となったセグメントを特定する必要がある。しかしながら、ファットポインタを用いる方式は、プログラム中の実行指令の記述に制約があるため、本実施形態はこれとは異なる原理で、基点セグメントを特定する。
本実施形態のプログラムデバッグ装置1は、検査対象のプログラムを図2に示すフローチャートのように実行することができる。すなわち、検査対象のプログラムのデバッグを開始すると、まずセグメントが割り当てられるアドレスのみを変更してセグメントの配置を変更し(ステップS21)、アドレス以外の条件を同一に保ちながら、セグメントの配置が変更されたプログラムを実行するとともに、メモリアクセスをトレースする。このとき、メモリアクセスにより参照された参照先アドレスを得るとともに、プログラムが実行された結果を示す実行結果、メモリアクセスがなされた回数を示すアクセス回数またはプログラムに内包される複数の実行指令が実行された順序を示す実行順序等が得られる。ただし、上記の実行結果、アクセス回数または実行順序は少なくとも一つが得られればよい(ステップS22)。そして、得られた実行結果、アクセス回数または実行順序の少なくとも一つが、プログラムが実行された全ての回において等しいか否かを判定する(ステップS23)。等しいと判定されたとき(ステップS23の真)、複数の実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの参照先アドレスに対してメモリアクセス解析処理を実行して、解析対象メモリアクセスが適正であるか否か判定する(ステップS24)。なお、メモリアクセス解析処理の詳細については後述する。
なお、上述した手順は、本実施形態に適用可能な手順の一例であり、その内容が相反しない範囲でその順序を変更可能である。
本実施形態のプログラムデバッグ装置1は、セグメントのアドレス配置変更に対して不変な動作を再現することを検査対象のプログラムに要求する。異なるアドレス配置を与えても、他の入力や動作条件が同一であれば、等しい実行順序でプログラムが処理され、等しい実行結果が出力されることを前提とする。
この前提が成立するならば、アドレス配置を変更してプログラムを複数回実行しても、メモリアクセスの回数、順番は等しく、互いに一致対応が取れるアクセスが存在する。よって、全てのメモリアクセスについては、トレース実行の組数分だけ、アクセス先アドレスを取り出すことができる。検査対象のプログラムが誤りを含んでいたために、異なる解釈順序でプログラムが実行された場合には、実行を開始してから対応関係が取れるまでのアクセスを検査対象とする。
また、メモリアクセス解析部132は、解析対象メモリアクセスの参照先アドレスに基づいて解析対象メモリアクセスにおけるアドレス指定の基点である基点セグメントを特定する基点セグメント特定部133を含んでもよい。基点セグメント特定部133が基点セグメントを特定できないとき、解析対象メモリアクセスが適正ではないと判定してもよい。
さらに、メモリアクセス解析部132は、基点セグメント特定部133により特定された基点セグメントに解析対象メモリアクセスの参照先アドレスが含まれるか否か判定する境界検査部134を含んでもよい。境界検査部134が、解析対象メモリアクセスにおける参照先アドレスがセグメントに含まれると判定するとき、解析対象メモリアクセスが適正と判定してもよく、解析対象メモリアクセスにおける参照先アドレスがセグメントに含まれないと判定するとき、解析対象メモリアクセスが適正ではないと判定してもよい。
メモリアクセス解析部132が、基点セグメント特定部133および境界検査部134を備えることによって、解析対象メモリアクセスの基点セグメントを特定することができ、これに基づいて、解析対象メモリアクセスの境界検査を行うこともできる。
ここで、説明のため、得られたアドレスの個数がT個、識別したいメモリセグメントがK個あるとし(Tは2以上の整数、Kは正整数)、第kセグメント(k=1,2,...,K)のサイズをsk 、t組目(t=1,2,...,T)のトレース実行において、第kセグメントに割り当てたメモリ領域の先頭アドレスをak (t) で表す。
プログラム中に正しく記述されたメモリアクセスは、その時点で有効な第kセグメントの先頭アドレスak (t) に、オフセット値iを加算して得られたアドレスを用いて、メモリ中のデータを参照する。第tトレース実行時のアドレス値をp(t) で表すと、このアドレスがセグメントkを基点として計算された場合、
p(t) =ak (t) +i ・・・(1)
という式が全てのt=1,2,...,Tに対して成立する。
さらに、このアクセスが正しい領域を指す場合、オフセット値iは、
0≦i≦sk −w ・・・(2)
という式を満たす。ここで、wは同時にアクセスされるアドレスの個数であり、例えば1アドレスに1バイトが割り当てられ、同時に4バイトのアクセスがなされる場合、w=4である。
上記基点セグメント特定処理は、アドレスp(1) ,・・・,p(T) から、(1)式を満たすセグメントkを特定する処理として解釈でき、上記セグメント境界検査処理は、(2)式を満たすかを判定する処理として解釈できる。プログラム実行が1回だけの場合(T=1)、(1)式を方程式として解くことはできないが、T≧2の条件で、適切なアドレス割当がなされていれば、セグメントkを求めることが可能である。
(1)式からオフセット値iを除去すると、
p(t+1) −p(1) =ak (t+1) −ak (1) ・・・(3)
という式が得られるので(t=1,2,・・・,T−1)、アドレス値からセグメント番号kを特定するには、t=1,2,・・・,T−1に対して(3)式を満たすセグメント番号kを探索すれば良い。その結果、(3)式を満たすセグメント番号kが存在しないとき、それは正しい計算により得られたアドレスを持たない不正なアクセスである。また、これを満たすセグメント番号kが一個だけ存在するとき、第kセグメントを基点セグメントとして特定することもできる。
このため、メモリアクセスのトレース出力からアドレス計算の基点セグメントを特定できるようにするためには、アドレス割当を工夫し、
Dk =(ak (2) −ak (1) ,ak (3) −ak (1) ,・・・,
ak (T) −ak (1) ) ・・・(4)
という式に示す(T−1)個の数値の組Dk が、セグメント番号kに対して一意な値を持つようにすれば良い。
Dk をセグメント番号kに対して一意にするアドレス割当方法は多数考えられるが、ここでは効果的な方法を3つ説明する。トレース出力は2組あれば十分であるため、いずれの例でもT=2とする。この場合、Dk は、
Dk =ak (2) −ak (1) =p(2) −p(1) ・・・(5)
という式で表され、1組目と2組目との実行で得られたアドレスの差p(2) −p(1) に等しい。
第1のアドレス割当方法は、Dk がセグメントの先頭アドレスak (1) を含むように配置する方法である。これは、隣接するセグメント間の先頭アドレスの差が、2組目の実行時に1組目の2倍になるようにすれば可能である。この時、
ak (2) −a1 (2) =2{ak (1) −a1 (1) } ・・・(6)
という式が成立し、これに(5)式を代入すると、
ak (1) =p(2) −p(1) −a1 (2) +2a1 (1) ・・・(7)
というセグメントの先頭アドレスak (1) を求める式を得ることができる。この方法は、2組目のプログラム実行時に2倍のメモリを必要とするが、アドレス計算の基点とされたセグメントを簡単に求めることが可能である。
図3は、本実施形態の第2のアドレス割当方法(セグメント配置方法)を説明するための図である。第2のアドレス割当方法は、Dk がセグメント番号を含むように配置する方法である。これは、図3に示すように、セグメントのアドレス大小順が番号kに一致するように配置し、隣接するセグメントの間に置かれた空白域の大きさが、1回目と2回目の実行時で、一定の差Δを持つように割り当てることで、可能になる。
この割当で成立する等式は、
ak+1 (2) −ak (2) =ak+1 (1) −ak (1) +Δ ・・・(8)
という式で表される(k=1,2,...,K−1)。異なるkにおける(8)式を合成することで、
ak (2) −ak (1) =a1 (2) −a1 (1) +(k−1)Δ
・・・(9)
という式が求まる(k=1,2,...,K)。この(9)式の左辺に(5)式を代入することで、
k=1+{p(2) −p(1) −a1 (2) +a1 (1) }/Δ
・・・(10)
という式が得られる。
(10)式は、トレースにより得られたアドレスp(1) ,p(2) から、基点セグメント番号kを、1回の計算で効率良く特定できることを示している。得られたkが非整数の場合や、有効なセグメント番号に該当しない場合には、そのアクセスを不正であると判断することができる。
図4は、本実施形態の第3のアドレス割当方法(セグメント配置方法)を説明するための図である。第3の方法は、図4に示すように、1組目と2組目との実行時で、セグメント配置順を真逆にするものである。ここで、セグメント番号kが2組目における配置順に等しいとすると、kに対してアドレスak (2) は単調増加であり、アドレスak (1) は逆に単調減少である。よって、両者の差ak (2) −ak (1) =Dk はkに対して単調増加であり、Dk がkに対して一意であることを意味する。ゆえに、第3の方法に従ってアドレス割当を行うことで、2個のアドレス値から基点のセグメントを特定可能である。
この第3の方法は、上述した第1の方法や第2の方法のように、単純な処理でセグメントを特定することはできない。しかしながら、(5)式を満たすkの探索にDk の単調性を利用した2分法を適用することができるため、計算時間は大きくならず、セグメント個数の対数時間で処理が可能である。また、第3の方法は、冗長なメモリ領域を必要としないため、メモリ使用効率の観点で優れている。
本発明は、以上説明したようなセグメントへのアドレス割当で、プログラムを複数回実行し、その結果、トレースされたメモリアクセスのアドレス値を比較することで、個々のメモリアクセスについて、アドレス計算の基点とされたメモリセグメントを特定し、その境界判定を正しく行うことが可能である。
本発明は、本発明に関連する技術で用いるガードゾーン方式のように、非連続なメモリアクセスを検出できないような制限を持たない。また、本発明は、本発明に関連する技術で用いるファットポインタ方式のように、プログラム中の変数やメモリの値に基点セグメントを記憶させる方法ではないため、アドレス値の論理演算や分解に対応できない等の制約がない。複数のパタンで与えたセグメントのアドレス配置に対して、プログラムが正常に動作する限り、本発明は、任意のアドレス値演算を含むプログラムについて、メモリアクセスの境界検査が可能である。
図5は本発明の第1の実施の形態によるメモリアクセスを解析する処理を示すフローチャートである。図5を参照して本発明の第1の実施の形態によるメモリアクセスを解析する処理について説明する。尚、図5に示す処理は、図1に示すプログラムデバッグ装置1のCPU(中央処理装置)(図示せず)が、コンピュータで実行可能なプログラムを実行することで実現される。
本実施の形態では、解析したいメモリアクセスについて、そのアクセスが参照する先のアドレスと、同一プログラムに異なるセグメント配置を与えて実行した場合に、同一アクセスが参照する参照先アドレスを取得する(ステップS1)。ここでは、合わせてT個の参照先アドレスが取得されたとし(Tは2以上の整数)、この参照先アドレスを、p(1) ,p(2) ,...,p(T) で表す。また、その際のT組のセグメント配置を、上記と同様に、第kセグメント(k=1,2,...,K)のサイズをsk 、t組目(t=1,2,...,T)のトレース実行において、第kセグメントに割り当てたメモリ領域の先頭アドレスをak (t) で表す。
プログラムデバッグ装置1は、T個の参照先アドレスが得られると(ステップS1)、(3)式の条件式を満たすセグメント番号kを探索する(ステップS2,S3)。その結果、プログラムデバッグ装置1は、有効なセグメント番号kが存在しなければ(ステップS4の偽)、このアクセス(解析対象アクセス)はどのセグメントもアドレス計算の基点としない不正アクセスであると判定する(ステップS8)。有効なセグメント番号kが存在する場合(ステップS4の真)、プログラムデバッグ装置1は、セグメント番号kに該当する第kセグメントを基点セグメントとして特定する。
ステップS5以降の処理は、上記の基点セグメント特定処理に続いて境界検査処理も連続して行う場合の手順である。プログラムデバッグ装置1は、基点アドレスに加算されたオフセットi(i=p(1) −ak (1) )を求め(ステップS5)、オフセットiが基点セグメントのサイズから当該参照先アドレスが指定するアドレスの数を減算した値以下の整数値である(0≦i≦sk −w)とき(ステップS6の真)、プログラムデバッグ装置1は、当該参照先アドレスがセグメントに含まれると判定し、当該メモリアクセス(解析対象メモリアクセス)が適正なものであると判定する(ステップS7)。また、上記範囲外であれば(ステップS6の偽)不正なアクセスであると判定する(ステップS8)。
これらの手順は、上記の本発明を実施する際のメモリセグメント配置方法で示した基点セグメントの特定方法を具体化したものであり、個々のメモリアクセスに対して有効な境界検査を行うことが可能である。
図6は本発明の第2の実施の形態によるメモリアクセスを解析する処理を示すフローチャートである。本発明の第2の実施の形態によるプログラムデバッグ装置は、図1に示す本発明の第1の実施の形態によるプログラムデバッグ装置1と同様の構成となっているので、これら図1及び図6を参照して本発明の第2の実施の形態によるメモリアクセスを解析する処理について説明する。尚、図6に示す処理は、図1に示すプログラムデバッグ装置1のCPUが、コンピュータで実行可能なプログラムを実行することで実現される。
本実施の形態において、プログラムデバッグ装置1は、上述した本発明の第1の実施の形態と同様にして、異なるアドレス配置の下でのプログラムを実行して得られたT個のアドレス値p(1) ,p(2) ,...,p(T) を取得する(ステップS11)。
次に、プログラムデバッグ装置1は、全てのtに対して、アドレスp(t) が含まれるセグメントk(t) を特定し、さらにオフセットi(t) を求める(ステップS12〜S16)。ここで、どの有効なセグメントにも含まれないアドレスp(t) が1個でも存在すれば(ステップS14の偽)、このメモリアクセスは不正なアドレス計算によりなされたものと判定する(ステップS19)。
プログラムデバッグ装置1は、全てのp(t) に対し、包含するセグメントとオフセットとが求まったならば、その両方が全てのtで一致するかどうかの比較を行う(ステップS17)。比較処理の結果、プログラムデバッグ装置1は、一個でも一致しないものがあれば(ステップS17の偽)、このアクセスが不正なアドレス計算によりなされたものであると判定する(ステップS19)。
これらの手順は、(1)式及び(2)式で示した条件式が、全てのtに対して成立することを確認する処理となっている。これによって、本実施の形態では、メモリアクセスの境界検査を行うことが可能となる。
本発明の第3の実施の形態は、静的に配置されるセグメントへのアクセスについて境界検査を行う方法の一例である。本実施の形態に必要な構成例について図1を参照して説明する。図1におけるメモリアクセストレース部11−1〜11−Tは、C言語で記述されたプログラム、またはC言語コンパイラでコンパイルした結果得られるオブジェクトファイル、スタティックライブラリから、実行形式のプログラムを生成して、シミュレータで実行し、メモリアクセスをトレースするT個の手段である(Tは2以上の整数)。
より具体的に説明すると、メモリアクセストレース部11−1〜11−Tは、C言語コンパイラを用いて必要なオブジェクトファイルを生成した後、アドレス割当部12の決定に基づいて、スタティックセグメントを適切なアドレスに配置しながらオブジェクトファイルを結合し、実行形式のプログラムを生成する。さらに、生成された実行形式のプログラムをシミュレータで実行し、その際に行われたメモリアクセスについて、アクセスした先のアドレスやアクセスを行わせる命令記述の位置情報をトレースし、データ解析部13に出力する。
アドレス割当部12は、プログラムのオブジェクトファイルに書かれたスタティックセグメントの情報を調べ、使用されるセグメントに対するアドレス配置をT組決定し、メモリアクセストレース部11−1〜11−Tに指示を伝える。この配置は、例えば、上述した第1〜第3の方法で決定されるものとする。
データ解析部13は、メモリアクセストレース部11−1〜11−Tがプログラムを実行した時に行われた命令実行の順序やプログラムが外部に出力する結果が、アドレス配置やその他の偶発的な要因に依存するものを除き、論理的に等しいことを確認する。
データ解析部13は、等価性が成立しないと判断した場合、エラーを出して解析を終了する。データ解析部13は、等価であった場合、個々のメモリアクセスについて、同一アクセスに対応するT組のトレース結果を取り出し、これが静的配置セグメントに対するメモリアクセスであるかを調べる。
これは、例えば、アドレス値の大小に基づいて判断してもよいし、あるいは対応する実行指令の記述を調べて判断しても構わない。判断の結果、データ解析部13は、このアクセスが検査対象であるならば、上述した本発明の第1の実施の形態や本発明の第2の実施の形態に示した境界検査部134と同様の構成を含み、そのメモリアクセスのアドレスがどのセグメントを基点として計算されたかを調べ、境界検査を行う。データ解析部13は、不正アクセスであれば、不正を検出したという結果と、不正を発生させた実行指令の記述箇所を示す情報を提示する。
本実施の形態は、以上の手順で、静的に配置されたデータセグメントへのアクセスについて、それが有効な範囲のアドレスを示すアクセスであるか境界検査を実施することが可能である。
尚、境界検査の対象となるセグメントは、検査目的に合わせて適当な大きさのものが選択されるとする。例えば、名称の異なる個々のグローバル変数(配列を含む)を別のセグメントとして扱うのも一つの例であるし、あるいは、プログラムをファイル等の単位で適当に分割し、同一ファイルに含まれる変数をまとめて一セグメントとして扱うのも一つの例である。
T個のメモリアクセストレース部11−1〜11−Tは、実行形式に変換したプログラムをシミュレータで動作させて、メモリアクセスをトレースするとして説明したが、これらの手段は、これと同様の結果を得られる手段や構成であれば、別のものを用いて構わない。
例えば、メモリアクセスをトレースする機能を備えたプロセッサやハードウェアを利用するのも一つの例である。あるいは、与えられたプログラムに適当な命令記述を追加し、メモリアクセスが行われる前に、データ解析部13にアドレス値を出力する処理がなされるようにしてもよい。この時、プログラムを変換する際には、元のプログラム記述において同一であったアクセスをトレース後に識別できるような工夫を持たせておく。あるいは、このようなT組のプログラム実行を同時に行いつつ、メモリアクセスの境界検査も自ら処理するプログラムを元プログラムから作成するのも一つの例である。
T個のメモリアクセストレース部11−1〜11−Tがプログラムを実行し、トレース結果をデータ解析部13に伝える手段や、タイミングについては、同様の効果が得られるならばいかなる方法であっても構わない。例えば、T個のトレース手段を同時に動作させて、メモリアクセスがなされた時点で、データ解析部13を動作させても良い。プログラムを最後まで実行して、得られたトレース結果をメモリやディスク装置等の記憶手段に出力した後、データ解析部13は記憶されたT組のトレース結果を読み出しながら、検査を行う手順でも構わない。
セグメントへのアドレス配置は、オブジェクトファイルを結合して実行ファイルを作成する際に指定すると説明したが、同様の作用があるならば、いかなる方法であっても構わない。例えば、入力されたC言語プログラムに、アドレス値を明示的に記述しても良いし、実行形式で与えられたプログラムを解析して、命令記述を変更する方法でも構わない。
本発明の第4の実施の形態は、動的にヒープから割り当てられるメモリセグメントについて、境界検査を行う方法の一例である。本実施の形態は、上記の本発明の第3の実施の形態と同様に、図1に示す構成で実施される。ここでは、上記の本発明の第3の実施の形態との違いのみについて説明する。
本実施の形態では、セグメントの配置アドレスが決定されるのは、検査対象のプログラムが実行中にヒープメモリ操作関数を呼び出す時である。ヒープ操作用の関数とは、主として指定サイズを持つ連続メモリを確保する関数とこれを解放する関数との組からなる。これは、C言語の標準ライブラリを用いる場合はmalloc,free関数、C++言語ならばnew,delete関数がこの例であり、実行環境のOS(Operating System)が提供する関数を用いても良いし、同様の機能を持つならば、プログラム自身が備える独自の関数でも良い。
本実施の形態では、メモリアクセストレース部11−1〜11−TがT組のプログラム実行を行う際に、これらのヒープ操作関数の呼び出しが異なるアドレス割当結果を返すようにし、適切な範囲検査を行えるようにする。これは例えば、プログラムを、C言語記述やオブジェクトファイルの形式で入力し、これを実行形式に変換する際に結合するヒープ操作関数ライブラリを、検査用のアドレス割当が可能なものに置換するのが一例である。
あるいは、ヒープ操作関数として動的に結合されるライブラリ[Linuxでは共用ライブラリ、Windows(登録商標)ではDLLがこの例にあたる]のものを使うように実行形式を作成し、実行時に使用するライブラリを置換するのも一つの例である。他には、シミュレータがプログラムを実行する際に、ヒープ操作関数の呼び出しを検査用の処理に置換する方法であっても良いし、プログラムを解析してから検査用のプログラムに変換する際に、検査用のアドレス割当が行われるようにしても良い。
本実施の形態では、メモリセグメントの確保と解放が動的に繰り返し行われるため、個々のアクセスの境界検査では、アドレス範囲の検査だけでなく、参照するセグメントがその時点で有効であるか、時間方向の検査も必要である。このため、本実施の形態では、ヒープ確保関数と解放関数の呼出もトレースし、メモリアクセスとの時間的な順序関係も検査できるようにする。この時、過去に使用され既に解放済みのセグメントを参照するアクセスと、新規に確保されたセグメントへのアクセスとを別個と認識するには、(4)式の値が全てのセグメント内で一意になるようにアドレスを割り当てる必要があるため、一度解放されたセグメントを再割り当てする際に注意が必要である。
以上の説明した構成によって、本実施の形態は、ヒープ上に配置されたデータセグメントへのアクセスについて境界検査を実施することが可能である。
本発明の第5の実施の形態は、スタック上に置かれるメモリセグメントについて境界検査を行う方法の一例である。本実施の形態も、本発明の第3の実施の形態と同様に、図1に示す構成で実施される。ここでは、本実施の形態と本発明の第3の実施の形態との違いのみについて説明する。
本実施の形態におけるスタック上のセグメントとは、C言語等で記述されたプログラムにおいて、関数内で宣言された自動変数(配列を含む)や、関数呼び出し時にスタック上に置かれる引数、戻りアドレスを包含する連続メモリ領域のことである。複数の変数をまとめて1セグメントとしても良く、その単位は検査目的に合わせて変えて良い。有効なセグメントの個数や配置は、プログラムの実行時に動的に変化する。配置先のアドレスは、プログラム実行時に与えられたスタックポインタを基点として、相対的に決定される。
T個のメモリアクセストレース部11−1〜11−Tは、このようなセグメントのアドレス割当を変更しながらプログラムを実行することが可能な環境とする。例えば、C言語で記述されたプログラムを入力とし、これを直接解釈しながら動作するインタープリタ型の実行環境を用いるのが一つの例である。
あるいは、C言語プログラムを実行形式に変換する際に、スタック利用の異なるプログラムを複数生成するのも一例である。複数のプログラムを生成せずに、スタックにアクセスする機械語命令が記述された位置をファイルに記録しておき、実行形式のプログラムを実行するシミュレータが、これを参照しながら動作を修正するのも一例である。
データ解析部13による境界検査では、その時点で有効なセグメント配置が正しく認識される必要があるため、C言語記述を実行形式に変換する実施の形態の場合には、各々の関数で使用されるセグメント情報や、プログラム実行中に関数が呼ばれた順番、スタックポインタの値など、適切な情報をトレースする必要がある。
以上の説明した構成により、本実施の形態は、スタック上に配置されたデータセグメントへのアクセスについて境界検査を実施することが可能である。
本発明の第6の実施の形態は、スタック上に置かれるセグメントについて、関数単位で境界検査を行う方法の一例である。本実施の形態も、上記の本発明の第5の実施の形態と同様に、図1に示す構成で実施される。ここでは、本実施の形態と本発明の第5実施の形態との違いのみについて説明する。
本実施の形態では、検査単位のセグメントを、個々の関数からスタックポインタ経由でアクセスされる連続的なメモリ領域として定義する。有効なセグメントや配置は、プログラム実行中に動的に変化する。
本実施の形態のプログラムデバッグ装置1は、プログラムのセグメントが、関数もしくはその関数から呼び出される子関数を含む関数群に対して、一つの関数または関数群内で、スタックポインタを基点とする相対アドレス参照が許可される連続メモリ領域として定義されてもよい。そして、プログラムの実行中に、関数の呼出が発生した時点で、当該関数に対応するセグメントをスタックポインタと共に異なるアドレスに移動させ、当該関数から呼出元に戻る時点で当該セグメントをスタックポインタと共に元のアドレスに移動させてもよい。
また、本実施の形態のプログラムデバッグ装置1は、第1の関数または関数群の実行指令の中で、第2の関数または関数群が呼び出された状態では、第1の関数または関数群に対して定義された連続メモリ領域から、第2の関数または関数群に対して定義された連続メモリ領域と重複する領域を除去した領域を、第1の関数または関数群に対して定義されたセグメントとしてもよい。
より具体的に定義すると、ある関数f1 の実行中、関数f1 は関数f2 から呼び出され、関数f2 は関数f3 から呼び出され、同様にして、関数fN-1 が関数fN から呼び出され(Nは1以上の整数)、関数fN が最初の関数である状態を考えると、この時、有効なセグメントは、N個定義される。
1つは、関数f1 からスタックポインタを用いて間接的にアクセスされるスタック上の連続メモリ領域(これを関数f1 のアクセス域と定義する)であり、2個目は、関数f2 のアクセス域から関数f1 のアクセス域を除いた連続メモリ領域、同様にしてN個目は、関数fN のアクセス域から関数fN-1 のアクセス域を除いた連続メモリ領域である。
ここで、関数fn (nは1以上の整数)のアクセス域は、スタックに積まれた関数fn の引数、戻りアドレス、関数fn 内で一時使用されるスタック領域(内部で別の関数を呼び出すために引数や戻り値を置く領域を含み、そこで呼び出される関数が内部で使用するスタック領域は含まない)、関数戻り値の出力に利用されるスタック領域(戻り値がレジスタで返す場合は存在しない)が含まれる。
図7は本発明の第6の実施の形態におけるプログラムデバッグ装置1の動作を説明するためのC言語プログラム例を示す図であり、図8は本発明の第6の実施の形態におけるプログラム実行時のスタック状態とスタックポインタの時間遷移とを示す図であり、図9は本発明の第6の実施の形態においてスタック移動処理がなされた場合のスタック状態とスタックポインタの時間遷移とを示す図である。
図8は、上記の定義を具体的に示す例であり、図7に示すC言語プログラム記述をコンパイルして実行した時のスタック使用状態とスタックポインタの時間遷移とを示している。この例では、cdeclと呼ばれる呼び出し規約に基づいて関数が呼び出されるものとする。
この規約では、アドレスが大きい方から小さくなる方に順に、関数の引数と戻りアドレスがスタックに積まれる。図8(a)は、図7に示すプログラムの12行目で関数func2が呼び出された直後の状態であり、引数b,a,戻りアドレスがこの順でスタックに置かれている。図8(b)は、図7に示すプログラムの14行目で関数func1を呼ぶ機械語命令を実行する直前の状態であり、関数func2で確保された配列変数bufと、関数func1に渡す引数p,xがスタックに置かれている。
図8(c)は、関数を呼ぶ機械語命令が実行された直後の状態であり、関数の戻りアドレスがスタックに積まれ、図8(d)は関数func1の実行中の状態、図8(e)は関数から戻る直前の状態、図8(f)は関数func1から関数func2に戻る機械語命令が実行された直後の状態である。
この例では、関数func2のアクセス域は、図8(b)に示す範囲のメモリ領域であり、(a)−(b),(e)−(f)において、この範囲が関数func2のセグメントである。図8(d)において、関数func1のアクセス域かつセグメントは、図8(d)の左側に示したスタック領域である。この状態において、関数func2のセグメントは、関数func1との重複分が除かれるので、図8(d)の右側に示す範囲の領域である。
本実施の形態に基づく境界検査も、上記の本発明の第5の実施の形態と同様に、図1に示す構成で実施される。但し、メモリアクセストレース部11−1〜11−Tが入力するプログラムは、C言語で記述されたものである必要はなく、実行形式に変換済みの形式で与えられても良い。その場合には、プログラムに含まれる関数を実行中に識別するための情報と、個々の関数がスタックポインタ経由でアクセスし得るセグメントのアドレス範囲が記述された情報を、補助情報として入力させるようにする。
スタック上のセグメント配置の変更処理は、メモリアクセストレース部11−1〜11−Tがシミュレータを用いてプログラムを実行する際に、シミュレータが処理される命令や命令の置かれたアドレスを監視し、関数の呼び出し命令と復帰命令とが実行されるタイミングで、スタックポインタとスタック上のセグメントの配置アドレスとを移動させる処理を、シミュレータに行わせることで実施する。
ここでは、上記の第1の方法に基づいて、これらのセグメントを配置して検査を行う例を示す。1組目のメモリアクセスのトレースを得る際は、図9に示すように、通常の場合と同様にプログラムを実行し、2組目のトレースを得る際には、Δバイトの隙間領域をセグメント間に挿入する。
図9は、2組目のトレースを得るために、図7と同じプログラムを実行した時のスタック使用とスタックポインタの時間遷移とを示している。隙間領域のサイズΔは4バイトであるとし、int変数やポインタ変数の格納域も4バイトであるとする。図9(b)は、関数func1への引数のスタック積み込みを終えて、関数呼び出し命令を実行する前の状態である。
この直後に、関数func1の呼び出し命令がシミュレータに検出されると、シミュレータには、関数func1のセグメントをΔバイトだけアドレス減少方向に移動させる。具体的には、スタックに積まれた引数p,xを左方向に移動し、スタックポインタの値を変更してから、関数呼び出しを処理し、図9(c)に示す状態に移行する。
その後、図9(d)で関数func1を実行し、図9(e)で関数func2への復帰命令を実行したことがシミュレータにより検出されると、シミュレータは引数p,xとスタックポインタを元の図9(b)の状態に復元する処理を行い、関数func2の残りの処理を実行する状態に移行する。
このような手順に従い、プログラムを実行してメモリアクセスをトレースすると、1組目のトレース実行時には、各々の状態で有効なセグメントが密に配置され、2組目のトレース時には、セグメント間にΔバイトの隙間領域が置かれる状態になり、関数に対応付けて定義されたセグメントに対して、図3に示す第1の方法に基づくアドレス割当がなされることが分かる。
本実施の形態では、この図9に示す配置で、プログラムを実行した時のメモリアクセスをトレースし、図8の配置の場合のトレース結果と比較することで、個々のメモリアクセスについて境界検査が可能である。
図7に示すプログラムを実行した場合について説明すると、図7に示すプログラムの6行目は関数func1のセグメントを参照する正当なアクセス、図7に示すプログラムの7行目は関数func2のセグメントを参照する範囲外のアクセスである。
これを、図8のスタック配置で実行すると、上記の6行目も7行目も共に変数resの置かれたアドレスへのメモリアクセスを発生させるので、単にメモリアクセスをトレースするだけでは両者を区別することができず、メモリアクセスの不正を検出することができない。
しかしながら、Δバイトの隙間を設けた図9では、7行目のアクセスが6行目と異なり、変数resではなく、戻りアドレスの置かれた隣のメモリ領域にアクセスを行う。この、図8に示す場合と図9に示す場合との違いから、7行目のアクセスと6行目のアクセスとのアドレス値から、6行目及び7行目のアクセスが参照するセグメントを特定することができ、これより、正しい境界検査が可能である。この場合には、6行目は問題なく実行され、7行目は範囲外のアクセスとして検出される。
尚、上記の説明では、プログラムに含まれる個々の関数について、スタックポインタを用いた相対アクセス参照が許可されたメモリの範囲を補助情報として入力するか、コンパイル時に取得する必要があるとしている。しかしながら、この情報を簡略化し、引数としてスタックに積まれるデータのバイト数のみとする発明の実施も可能である。
この場合には、実行中の関数のアクセス域の下限(図9の左方向の境界)が分からないので、例えばスタックとして与えられたメモリ領域の下限までをその関数のセグメントとする。呼び出しスタック中の関数については、それ以降に呼ばれた関数のセグメントと重複する領域が除外されるので、有効なセグメントの下限は関数呼び出し時のポインタと、引数のバイト数とから求めることができる。
上記の説明では、関数の呼び出し規約がcdecl方式であるとしたが、他の呼び出し規約、例えばPASCALやfastcall等の方式であっても構わない。また、上記の説明では、関数呼び出し命令をシミュレータが処理する直前と復帰命令を処理した直後に、スタック上のセグメント移動処理を行わせるようにしたが、これが関数呼び出し命令の実行直後や復帰命令の実行直前であっても良い。関数呼び出しに伴う戻りアドレスのスタック退避が、問題を引き起こさないように、セグメントの定義を修正する。
上記の説明では、1つの関数に対して1つのセグメントを定義したが、ある関数から呼び出される子関数や孫関数も含めて、これを一つの関数群として扱い、関数群にセグメントを1つ定義する実施であっても構わない。
本実施の形態は、以上説明した構成や動作によって、スタック上に配置されたセグメントへのアクセスについて関数単位で境界検査を実施することが可能である。
本発明の第7の実施の形態では、複数種類のセグメントへの検査を同時に行う例として、静的に配置されるセグメントとヒープ上のセグメントとに対する境界検査を同時に実施する例を示している。本実施の形態の構成は、上述した本発明の第1及び第2の実施の形態と同様に、図1で示される構成を用いている。
本実施の形態の各構成要素は、本発明の第1の実施の形態と本発明の第2の実施の形態とにそれぞれ示す動作の両方を行う。その動作は、本発明の第1の実施の形態と本発明の第2の実施の形態とでそれぞれ説明したものの単純な組み合わせであるため、詳細な説明を省略する。
複数の検査を組み合わせる際に注意すべき点は、トレースされたメモリアクセスのアクセス先がスタックであったか、ヒープであったか、種類を判別する方法である。これは、様々な実施の形態が考えられる。一つは、種類によらず全セグメントの中で、セグメントを特定するためのアドレス差分Dk [上記の(4)式にて算出]を一意に設定する実施の形態がある。他には、得られたアクセス先のアドレスの範囲でセグメントの種類を絞り込んでから、種類毎に個別の検査を行う例がある。
このような点に注意すれば、本発明に基づいて複数種類のセグメントへのメモリアクセス境界検査を同時に実施することが可能である。これは、静的なセグメントとヒープセグメントとの組み合わせ以外であっても、同様である。
図10は本発明の第8の実施の形態によるプログラムデバッグ装置2の構成例を示すブロック図である。図10には、境界検査に利用される複数のメモリアクセストレース結果を得るための手段の構成や動作を示している。図10において、本発明の第8の実施の形態によるプログラムデバッグ装置2は、複数コンテキスト並列実行部21と、メモリセグメントアドレス割当部(以下、アドレス割当部)22と、データ解析部23とを備えている。
ここで、データ解析部23は、実行結果解析部231、メモリアクセス解析部232を有してもよい。さらに、メモリアクセス解析部232は、基点セグメント特定部233および境界検査部234を含んでもよい。本実施形態におけるアドレス割当部22およびデータ解析部23、またデータ解析部に内包される実行結果解析部231、メモリアクセス解析部232、基点セグメント特定部233および境界検査部234は、それぞれ第1の実施の形態にて説明したアドレス割当部12、データ解析部13、実行結果解析部131、メモリアクセス解析部132、基点セグメント特定部133および境界検査部134と同様の動作を行ってもよい。
本実施の形態では、プログラムの実行コンテキストを複数保持し、それらを同時に更新する複数コンテキスト並列実行部21を用いて、複数のアドレス割当条件下でのプログラム実行とメモリアクセスのトレースとを行う。このプログラム実行は、実際に複数コンテキストを並列実行可能なハードウェアを用意して行っても良いし、仮想的に構築しても良い。
より具体的には、本実施形態のプログラムデバッグ装置2に備えられる複数コンテキスト並列実行部21は、複数コンテキスト並列実行部21が使用するレジスタとメモリとに複数の格納値を記憶させられる仮想実行環境を生成し、レジスタとメモリとに、アドレス割当部22にて変更されたセグメントの配置に基づいてプログラムを実行した場合に得られる複数の格納値を記憶させることでプログラムを実行して参照先アドレスを求めてもよい。または、仮想実行環境を用いてプログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得てもよい。
例えば、上記の非特許文献2に記載のようなシャドウ値を備える仮想実行環境を構築し、1組目以外のコンテキストをシャドウ値として保存することで、検査を実施するのも一例である。この例で、実行コンテキストは、プロセッサが備えるレジスタ及びメモリの数値格納状態や、その他、プログラム実行手段の状態を意味する。
図11(a)は、2組のプログラムを並列実行する過程でのメモリ状態を示している。図11(a)においては、左側から3個のセグメントが、2つのコンテキストで異なるアドレスに配置されている。アドレス割当の影響を受けない変数a,b,cは共通の値を保持し、ポインタ変数pは2つのコンテキストで違うアドレスを保持している。
上述したように、本発明は、検査対象のプログラムの論理的な動作がセグメントへのアドレス割当の変更に対して不変であることを前提とする。この条件の成立性は、複数コンテキスト間でプログラム実行順が一致するか、実行過程を逐次比較することで確認することが可能である。
この時、論理的には一致した動作であるが、アドレス割当に依存する除去できない分岐が含まれる時(例えば、アドレスの端数を切り詰める処理をif文で行うのがこれに該当する)には、これを不正と判断しないように回避するため、何らかの工夫を取り入れておく。例えば、この工夫としては、検査実行時に例外を指定させる方法や、プログラム記述を変換する方法、あるいはアドレス配置に制約を加える方法がある。
この実施の形態で、プログラム実行に要する時間を短縮する工夫として、全てのコンテキストで等しい処理が行われることが予測できる場合には、これを利用して複数回の命令実行処理を1回にすることで、シミュレーションに要する時間を短縮することも可能である。例えば、全てのコンテキスト間でレジスタの格納値が等しい状態で、メモリにアクセスする命令や、セグメントの配置アドレスに依存する数値を扱わない命令記述がなされている区間については、このような時間短縮が可能である。
他には、コンテキストの並列更新を簡易に行うため、上記のような論理動作の一致検査を省略し、1組目以外のコンテキストでのプログラム処理順が、1組目に全て一致すると仮定して、複数コンテキストの更新を行う方法もある。
以上説明した構成により、本実施の形態は、複数コンテキストの同時更新を行う実行環境を用いることで、一度の検査でメモリアクセスの境界違反を調べることが可能である。
本発明の第9の実施の形態は、上述した本発明の第8の実施の形態と同様に、一度の実行で複数コンテキストのトレース結果を得る例であり、図10に示される構成と同様の構成で実行される。この実行環境として、上記の非特許文献2に記載のシャドウ値に類する仕組みを用いる。但し、本実施の形態は、本発明の第8の実施の形態とは異なり、1つのコンテキストを主コンテキストとして選択し、他のコンテキストの格納値をシャドウ値として、主コンテキストの格納値である主値に関連付けて記憶している。この関連付けは、論理的な意味で同一のセグメントの同一アドレスオフセットで参照されるデータ及びレジスタ同士を対応させる方法で行われる。
本実施形態のプログラムデバッグ装置2は、複数コンテキスト並列実行部21は、プログラムで使用される変数に、複数の格納値を記憶させられる仮想実行環境を生成し、各々の変数に、アドレス割当部22にて変更されたセグメントの配置に基づいてプログラムを実行した場合に得られる複数の格納値を記憶させることで、プログラムを実行して参照先アドレスを求めてもよい。もしくは、仮想実行環境を用いてプログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得てもよい。
図11は本発明の第8の実施の形態及び本発明の第9の実施の形態と本発明に関連する方式との違いを説明するための図である。図11(a)は、本発明の第8の実施の形態の実行状態を示し、ここでは、2通りのセグメント配置で実行コンテキストが別個に保持される。
これに対して、本実施の形態を示す図11(b)では、1組目のコンテキストが主コンテキストとして扱われ、2組目のコンテキストは、シャドウ値として記憶される。さらに、シャドウ値の格納先アドレスは、2組目のコンテキストのアドレス配置ではなく、これと論理的に同一のデータが主コンテキストにおいて格納される先のアドレスである。
例えば、配列変数b[5]の先頭要素b[1]は、図11(a)の第2コンテキストにおいて2CH番地に格納されるのに対して、図11(b)では、同様に2CH番地に格納されたコンテキストを仮想的に保持しつつ、実際の値の格納先は、第1コンテキストの格納先である24H番地のデータのシャドウ領域である。尚、図11(b)にシャドウ値として格納される数値は、あくまでも図11(a)の2重実行を仮定してのものであるので、24H番地に格納されるポインタpが指すアドレスのシャドウ値は、24H番地ではなく2CH番地である。
この動作から分かるように、本実施の形態と本発明の第8の実施の形態とで行われる複数のプログラム実行は、本質的に等価な処理を行っており、本発明の第8の実施の形態と同等の境界検査を実施することが可能である。
本発明の第9の実施の形態を、Nethercoteらの方法(非特許文献5に記載の方法)と比較する。Nethercoteらの方法は、実行形式で与えられたプログラムの実行中に、セグメントのアドレスが代入されたレジスタやメモリの数値を追跡し、シャドウ値に、ポインタか、非ポインタかを示す情報と、参照セグメントを示す識別子(ここではセグメントの先頭アドレスとする)とを格納する。
図11(c)に、同じ検査をNethercoteらの方法で行った場合の状態を示す。この状態と本実施の形態に基づく例[図11(b)]との違いは、シャドウ値に格納される情報の表現形式である。変数pが左から2組目のセグメントを指すポインタであることを、Nethercoteらの手法の図11(c)では、変数pの値が記憶される38H番地のシャドウ値に、参照先セグメントの先頭アドレスの20H番地を持たせることで記憶する。
これに対して、本実施の形態による図11(b)では、仮想コンテキストで実行した場合の値2CHをシャドウ値として記憶し、シャドウ値と主値との差(2CH−24H=8)が、2組目のセグメントの先頭アドレスの仮想配置と主配置との差(28H−20H=8)に一致することで、参照先セグメントを表現している。
本実施の形態は、Nethercoteらの方法と同等の検査を実行できるだけでなく、アドレス値に対する任意の演算がプログラムに含まれていたとしても、検査が可能となるという利点を備える。例えば、4バイトのポインタpを、上位2バイトと下位2バイトとに分解して、他のメモリ領域に格納すると、Nethercoteらの方法はシャドウ値に参照セグメント情報を追跡記憶させることが不可能になるが、本実施の形態は2通りのコンテキストを保持すれば良いだけなので、特に制約を受けない。
従って、本実施の形態は、Nethercoteらの方法の課題を解決する改良手法と解釈することが可能である。アドレス値と所属セグメント識別子とからなるファットポインタは、本発明の原理に基づいて、アドレスの主値と、異なるアドレス割当でプログラムを実行した場合に代入されるアドレス値を仮想的に求めたシャドウ値との組で表現することが可能であり、これは計算自由度の点で優れる表現である。
尚、このように、シャドウ値を利用できる仮想実行環境を用いると、本実施の形態をNethercoteらの方法と組み合わせて本発明を実施することも可能である。例えば、実行コンテキストのシャドウ値に、本発明のシャドウ値に加えて基点とするセグメントへのポインタの両方を持たせても良い。あるいは、どちらか片方の表現を選択するフラグを設け、基点セグメントへのポインタによる追随が不可能になった場合に限り、本発明の表現でシャドウ値を持たせる方法も一つの例である。
本発明の第10の実施の形態は、上記の本発明の第9の実施の形態と同様に、異なるアドレス配置でプログラムを実行した場合の実行コンテキストを、シャドウ値として主コンテキストに組み合わせて記憶させる方法の例である。
本発明の第9の実施の形態では、実行形式プログラムを解釈して処理する際のレジスタやメモリ格納値を、プログラムの実行コンテキストと扱っているが、本実施の形態では、C言語等で記述された変数の状態を実行コンテキストとみなし、異なるアドレス配置条件で実行した場合に得られる数値を、個々の変数に多重記憶させている。
これを実施する方法としては、実行環境として多重のコンテキスト更新機能を備えたC言語インタープリタを用いる方法や、これと等価な動作を行う実行形式プログラムを直接生成する方式があるが、ここでは、検査したいC言語プログラムを、等価な動作を行うC言語やC++言語のプログラムに変換してから、これを実行形式に変換して実行する手順により、検査を行う方法について説明する。
本実施の形態は、非特許文献2に記述されたFail Safe Cコンパイラと同様な処理手段とこれを用いる手順で、入力されたプログラムを変換することで、有効なセグメント外を参照する危険性があるメモリアクセスの前に、アドレス値の境界検査を自ら行い、不正であれば停止し、妥当であればプログラムに記述された処理を継続する実行形式のプログラムを生成する。
本実施の形態で、C言語プログラムを解析して、実行時に境界検査を行わせる処理の内容は、境界検査の仕組みを除いて、Fail Safe Cと共通である。本実施の形態では、Fail Safe Cと同様に、セグメントメモリを参照するポインタ型変数を、参照先セグメントの情報を保持する倍のサイズを持つ拡張構造体変数に置換し、また、ポインタ型の型変換により得られたアドレスを保持する整数型変数を、拡張構造体の変数に置換する。
また、本実施の形態では、メモリセグメントを動的に確保する処理や、メモリセグメントのアドレスを得る処理に修正を加えて、前記の拡張構造体に適切な情報を設定する点と、メモリアクセス前に、アドレス値の境界検査を実施して、範囲外であるならば処理を中断する動作を追加する点も共通である。
本実施の形態とFail Safe Cとの差異は、Fail Safe Cの境界検査がファットポインタ方式に基づくのに対して、本実施の形態は、本発明の第1の実施の形態、本発明の第2の実施の形態で説明した方法で境界検査が実施される点である。
図12は本発明の第10の実施の形態で行われるプログラム記述変換の特徴的な部分を示す図である。Fail Safe Cは、図12に示すように、ObjType型のポインタ型変数をFatPtr<ObjType>構造体変数に変換し、参照先セグメントの先頭を指すポインタbaseとオフセットoffsetとを記憶させている。
これに対し、本実施の形態では、DualPtr<ObjType>構造体に置換し、実行時の参照先を示すポインタ値valueと、アドレス割当を変更して別の実行をした場合に格納されるポインタ値shadow_valueとを記憶させている。
また、ポインタを整数化した値が格納されるValType型変数については、Fail Safe CがこれをFatInt<ValType>型に置換し、本来の格納値valueに加えて、変換前のポインタの参照先セグメントをbaseに持たせるのに対して、本実施の形態は、これをDual<ValType>型に置換し、本来の格納値valueに加え、アドレス割当を変更して別の実行をした場合に格納される仮想的なポインタ値shadow_valueを記憶させている。
さらなる相違点としては、Fail Safe Cが、ValType型として取りうる型を、アドレス値を表現するのに十分なビット幅を持つ型に制約し、FatInt<ValType>型に置換される変数を限定しているが、本実施の形態は、これに満たない任意の数値型であって良いとし、Dual<ValType>型に置換される変数を、セグメントの配置アドレスの変更により、格納値が変わりうる変数全てに拡大している。
DualPtr<ObjType>型、Dual<ValType>型の変数に対して行われる代入、型変換、数値計算のプログラム記述は、変換前のプログラムが記述する動作がvalueメンバ間で行われ、それと同時にshadow_valueメンバ間でも等しい動作が行われるプログラムに変換する。その際、メモリセグメントのアドレスが含まれる記述、具体的には、アドレス演算子&、配列名記述、malloc関数が返すアドレスを用いる記述は、valueメンバとshadow_valueメンバとで異なるアドレス値を用いるようにする。
これを具体的に説明すると、valueメンバの計算では、実行中のセグメントアドレスを利用し、shadowメンバの計算では、例えば、上述した本発明の3つのアドレス割当方法のいずれかに従って配置されたセグメントのアドレスを使用するように変換する。尚、検査対象に含まれないセグメントを参照する場合には、shadow_valueとvalueとに等しい値を格納する処理に変換する。
DualPtr<ObjType>型のポインタ変数に、間接参照演算子*や配列参照演算子[]を作用させて行われるメモリアクセスについては、Fail Safe Cと同様に、境界検査を事前に行い、不正であればプログラム実行を中止する処理を追加する。境界検査の手順は、Fail Safe Cと異なり、2つのアドレスvalueとshadow_valueとを用いて本発明の第1の実施の形態、または本発明の第2の実施の形態に示した手順で行われる。
ポインタ変数が正しいアドレスを指すと判断した場合には、valueメンバが指すアドレスに置かれたObjType型の変数を参照して、元プログラムに記述された処理を行うようにする。ここで、shadow_valueは、検査用に用意された仮想上のアドレスであるため、実際のメモリアクセスには使用されない。
DualPtr<ObjType>型、Dual<ValType>型の変数を用いて、プログラムの解釈順序を分岐させる実行指令、具体的にはif,for,while等の制御命令文や、?,&&,||演算子の評価式を含む実行指令文については、valueとshadow_valueとを評価した結果が同一の分岐先を返す場合に分岐先の処理を続行し、異なる結果を返した場合に異常であるとしてプログラム実行を停止する処理に置換して、実行形式を生成する。
以上説明したように、本実施の形態に基づいて、Cプログラムを実行形式に変換して、これを実行すると、プログラムの実行回数は1回でありながら、DualPtr型とDual型のvalueメンバとshadow_valueメンバとに、2通りのセグメント配置を与えてプログラムを個別に実行した場合と等価な結果が得られる。このアドレス値を用いることで、本発明に基づく有効な境界検査を実施することができる。
本発明に関連するファットポインタ方式に基づくFail safe Cは、異なるセグメントを参照するFatPtr<ObjType>型ポインタ間の減算を行うプログラム記述や、FatInt<ValType>型に格納されたアドレス値に任意の論理演算を行うプログラム記述の検査を実施することができない。あるいは、ファットポインタ方式に基づくFail safe Cは、ポインタの指すアドレスを上位と下位に分離して、アドレス値の半分のビット幅を持つ数値型に代入する処理の記述にも対応できない制約がある。
これに対して、本実施の形態は、ポインタ変数が参照するセグメントを記憶する方式ではないため、上記に示した制約を持たない。2つの値valueとshadow_valueとを得るために仮定したアドレス割当でプログラムが適切に動作する限り、有効な境界検査を行う実行形式が生成される。
尚、本実施の形態を変形して、本発明に関連するファットポインタ方式を組み合わせ、DualPtr,Dual構造型にbaseポインタを追加することも可能であり、それも一つの例である。あるいは、2種類の表現をプログラム実行中に切り替えるプログラムを生成するのも本実施の形態の一例である。
この他、本実施の形態は、C言語のプログラムを検査の対象としたが、ポインタ変数が用意された別の言語で書かれたプログラムに対しても、上記と同様の実施の形態を構成することが可能である。
このように、本発明は、メモリセグメントへのアドレス割当を変更して検査対象のプログラムを実行した場合に、同一のプログラム記述によってなされる参照先アドレスを、実際にプログラムを複数回実行する方法で、もしくは仮想的に等価な方法で求め、この情報から、アドレス計算の基点となった参照先セグメントを特定し、セグメント境界への整合性を検査する。
参照先セグメントの特定は、変更前後のセグメント先頭アドレスの差分が、セグメントを識別するための情報を含むようにしておくことで可能である。この原理により、本発明は、プログラム実行時になされる個々のメモリアクセスについて、確実な方法でセグメント境界検査を実施可能である。特に、本発明に関連するガードゾーン方式で検出できない不連続な不正メモリアクセスについても、検出が可能である。この効果は、デバッグの効率性を高め、テストの有効性を高める上で重要である。
また、本発明は、上記のセグメントへのアドレス割当方法として、上述した第1のアドレス割当方法、第2のアドレス割当方法により、容易に実施できる参照先セグメントの特定方法を与えている。あるいは、本発明は、第3のアドレス割当方法により、メモリ使用効率に優れる参照先セグメントの特定方法を提供している。
なお、本発明のセグメントへのアドレス割当を行う手順について、第1実施形態において図2を用いてセグメントが割り当てられるアドレスのみを変更してセグメントの配置を変更した次に、対象のプログラムを実行してメモリアクセスをトレースするように説明した。しかし、ヒープ上に配置されたデータセグメントへのメモリアクセスについて境界検査を実施する第4の実施の形態やスタック上に配置されたデータセグメントへのアクセスについて境界検査を実施する第5の実施の形態においては、この順序とはならない。これらの実施の形態においては、セグメントへのアドレス割当は、プログラム実行中にメモリセグメントを確保する実行指令を解釈した時点で行う。すなわち、図2におけるステップS22がステップS21を内包するフローで実行される。
さらに、本発明は、本発明に関連するファットポインタ方式の境界検査と異なる原理に基づくため、本発明に関連する方式のように、アドレス値の任意演算操作に対応できないといった制約を持たず、広範囲のプログラムに対して、メモリアクセスの境界検査が可能である。
さらに、本発明は、適切な情報を含むプログラム記述が与えられ、適切なトレース実行環境を用いて、複数のセグメント配置条件でのプログラム実行がなされる限り、対象とするセグメントの種類を問わない。本発明は、静的に配置されるセグメント、ヒープセグメント、スタック上のセグメント、いずれに対しても実施が可能である。
本発明は、複数回のアドレス値を求める手順として、単純に複数回の実行を行う実施形態や、1回の検査実行で複数コンテキストの実行結果を得る形態等、様々な手順の実施形態が可能である。また、本発明は、本発明に関連するファットポインタ方式に基づく実行形式プログラムの境界検査手法や、C言語記述から動的な境界検査を行うプログラムを生成する手法と組み合わせて実施することも可能である。このように、本発明は、検査目的や状況に合わせて、適切な形態を選択可能である。
本発明は、適切な条件の下で、C言語のようにポインタ変数を用いる各種の言語で記述されたソースファイルや、ソースファイルを実行形式にした実行形式ファイルに対しても適用可能である。また、ソースファイルをコンパイルした結果得られるオブジェクトファイルであってもよい。プログラムの実行環境については、適切な機能を備え、適切な構成で動作する限り、ハードウェア上の実動作環境、シミュレータ、インタープリタであっても、プログラムを変換して検査を自ら行うプログラムを生成する方法であっても、本発明をそれらに適用することが可能である。
以上、実施形態を参照して本願発明を説明したが、本願発明は上記実施形態に限定されるものではない。本願発明の構成や詳細には、本願発明のスコープ内で当業者が理解し得る様々な変更をすることができる。
(付記1)本発明のプログラムデバッグ方法は、プログラムの実行時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスをデバッグするプログラムデバッグ方法であって、前記記憶領域のアドレスのうち前記セグメントが割り当てられるアドレスのみを変更して前記セグメントの配置を変更するアドレス割当ステップと、
前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行ステップと、前記アドレス割当ステップと前記プログラム実行ステップとを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析ステップと、
前記実行結果解析ステップにて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析ステップと、を備えることを特徴とする。
(付記2)前記プログラムは、ポインタ変数を用いる各種の言語で記述されるソースファイル、前記ソースファイルを実行形式にした実行形式ファイルおよび前記ソースファイルをコンパイルした結果得られるオブジェクトファイルのいずれかであることを特徴とする付記1に記載のプログラムデバッグ方法であっても良い。
(付記3)前記メモリアクセス解析ステップは、前記解析対象メモリアクセスの参照先アドレスに基づいて前記解析対象メモリアクセスにおけるアドレス指定の基点である基点セグメントを特定する基点セグメント特定ステップを含み、
前記基点セグメント特定ステップが前記基点セグメントを特定できないとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記1または2に記載のプログラムデバッグ方法であっても良い。
(付記4)前記メモリアクセス解析ステップは、前記基点セグメント特定ステップにより特定された前記基点セグメントに前記解析対象メモリアクセスの参照先アドレスが含まれるか否か判定する境界検査ステップを含み、前記境界検査ステップが、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれると判定するとき、前記解析対象メモリアクセスが適正と判定し、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれないと判定するとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記3に記載のプログラムデバッグ方法であっても良い。
(付記5)前記基点セグメント特定ステップは、前記解析対象メモリアクセスの参照先アドレスのうち第1の回において参照された第1参照先アドレスと第2の回において参照された第2参照先アドレスの差分が、同一の識別番号が割り当てられたセグメントに対して前記第1の回にて割り当てられた第1先頭アドレスと前記第2の回にて割り当てられた第2先頭アドレスの差分と一致したとき、当該セグメントを前記基点セグメントとして特定することを特徴とする付記4に記載のプログラムデバッグ方法であっても良い。
(付記6)前記アドレス割当ステップは、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの差分を、前記セグメントの中で一意な値で与えることを特徴とする付記5に記載のプログラムデバッグ方法であっても良い。
(付記7)前記アドレス割当ステップは、前記セグメントの配置を変更するとき、前記セグメントのうち第1セグメントと第2セグメントとの変更後の先頭アドレスの差分を変更前の先頭アドレスの差分の整数倍とすることを特徴とする付記5に記載のプログラムデバッグ方法であっても良い。
(付記8)前記アドレス割当ステップは、前記セグメントの配置を変更するとき、隣接する前記セグメントの間に置かれた空白域の大きさを変更前より変更後の方が一意の値だけ大きくなるように変更することを特徴とする付記5に記載のプログラムデバッグ方法であっても良い。
(付記9)前記アドレス割当ステップは、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの大小関係が逆順になるようにすることを特徴とする付記5に記載のプログラムデバッグ方法であっても良い。
(付記10)前記境界検査ステップは、前記解析対象メモリアクセスの参照先アドレスから前記基点セグメントの先頭アドレスを減算して得られるオフセットを求め、前記オフセットが前記基点セグメントのサイズから当該参照先アドレスが指定するアドレスの数を減算した値以下であるとき、当該参照先アドレスが前記セグメントに含まれると判定することを特徴とする付記5乃至9のいずれかに記載のプログラムデバッグ方法であっても良い。
(付記11)前記プログラムのセグメントは、ヒープ上に動的に確保されるセグメントであることを特徴とする付記1乃至10のいずれかに記載のプログラムデバッグ方法であっても良い。
(付記12)前記プログラムのセグメントは、前記プログラムの実行時に静的に配置されるセグメントであることを特徴とする付記1乃至10のいずれかに記載のプログラムデバッグ方法であっても良い。
(付記13)前記プログラムのセグメントは、スタック上に配置されるセグメントであることを特徴とする付記1乃至10のいずれかに記載のプログラムデバッグ方法であっても良い。
(付記14)前記プログラムのセグメントは、関数もしくはその関数から呼び出される子関数を含む関数群に対して、一つの関数または関数群内で、スタックポインタを基点とする相対アドレス参照が許可される連続メモリ領域として定義され、前記プログラムの実行中に、関数の呼出が発生した時点で、当該関数に対応するセグメントをスタックポインタと共に異なるアドレスに移動させ、当該関数から呼出元に戻る時点で当該セグメントをスタックポインタと共に元のアドレスに移動させることを特徴とする付記13に記載のプログラムデバッグ方法であっても良い。
(付記15)第1の関数または関数群の実行指令の中で、第2の関数または関数群が呼び出された状態では、第1の関数または関数群に対して定義された前記連続メモリ領域から、第2の関数または関数群に対して定義された前記連続メモリ領域と重複する領域を除去した領域を、第1の関数または関数群に対して定義されたセグメントとすることを特徴とする付記14に記載のプログラムデバッグ方法であっても良い。
(付記16)前記プログラム実行ステップは、前記プログラム実行ステップが使用するレジスタとメモリとに複数の格納値を記憶させられる仮想実行環境を生成し、前記レジスタと前記メモリとに、前記アドレス割当ステップにて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで前記プログラムを実行して参照先アドレスを求めること、または、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記1に記載のプログラムデバッグ方法であっても良い。
(付記17)前記プログラム実行ステップは、前記プログラムで使用される変数に、複数の格納値を記憶させられる仮想実行環境を生成し、各々の変数に、前記アドレス割当ステップにて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで、前記プログラムを実行して参照先アドレスを求めること、もしくは、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記1に記載のプログラムデバッグ方法であっても良い。
(付記18)本願発明のプログラム変換方法は、第1の情報処理装置がプログラムを実行する時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスの検査処理を第2の情報処理装置に行わせるデバッグ用プログラムを、前記プログラムを変換して生成するプログラム変換方法であって、前記デバッグ用プログラムは、前記記憶領域のアドレスのうち前記セグメントが配置されるアドレスのみを変更して前記セグメントの配置を変更するアドレス割当処理と、前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行処理と、前記アドレス割当処理と前記プログラム実行処理とを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析処理と、前記実行結果解析処理にて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析処理と、を前記第2の情報処理装置に行わせることを特徴とする。
(付記19)本願発明のプログラムデバッグ装置は、プログラムの実行時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスをデバッグするプログラムデバッグ装置であって、前記記憶領域のアドレスのうち前記セグメントが配置されるアドレスのみを変更して前記セグメントの配置を変更するアドレス割当手段と、前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行手段と、
前記アドレス割当手段と前記プログラム実行手段とにより前記プログラムを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析手段と、前記実行結果解析手段にて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析手段と、を備えることを特徴とする。
(付記20)前記プログラムは、ポインタ変数を用いる各種の言語で記述されるソースファイル、前記ソースファイルを実行形式にした実行形式ファイルおよび前記ソースファイルをコンパイルした結果得られるオブジェクトファイルのいずれかであることを特徴とする付記19に記載のプログラムデバッグ装置であっても良い。
(付記21)前記メモリアクセス解析手段は、前記解析対象メモリアクセスの参照先アドレスに基づいて前記解析対象メモリアクセスにおけるアドレス指定の基点である基点セグメントを特定する基点セグメント特定手段を含み、前記基点セグメント特定手段が前記基点セグメントを特定できないとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記19または20に記載のプログラムデバッグ装置であっても良い。
(付記22)前記メモリアクセス解析手段は、前記基点セグメント特定手段により特定された基点セグメントに前記解析対象メモリアクセスの参照先アドレスが含まれるか否か判定する境界検査手段を含み、前記境界検査手段が、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれると判定するとき、前記解析対象メモリアクセスが適正と判定し、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれないと判定するとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記21に記載のプログラムデバッグ装置であっても良い。
(付記23)前記基点セグメント特定手段は、前記解析対象メモリアクセスの参照先アドレスのうち第1の回において参照された第1参照先アドレスと第2の回において参照された第2参照先アドレスの差分が、同一の識別番号が割り当てられたセグメントに対して前記第1の回にて割り当てられた第1先頭アドレスと前記第2の回にて割り当てられた第2先頭アドレスの差分と一致したとき、当該セグメントを前記基点セグメントとして特定することを特徴とする付記22に記載のプログラムデバッグ装置であっても良い。
(付記24)前記アドレス割当手段は、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの差分を、前記セグメントの中で一意な値で与えることを特徴とする付記23に記載のプログラムデバッグ装置であっても良い。
(付記25)前記アドレス割当手段は、前記セグメントの配置を変更するとき、前記セグメントのうち第1セグメントと第2セグメントとの変更後の先頭アドレスの差分を変更前の先頭アドレスの差分の整数倍とすることを特徴とする付記23に記載のプログラムデバッグ装置であっても良い。
(付記26)前記アドレス割当手段は、前記セグメントの配置を変更するとき、隣接する前記セグメントの間に置かれた空白域の大きさを変更前より変更後の方が一意の値だけ大きくなるように変更することを特徴とする付記23に記載のプログラムデバッグ装置であっても良い。
(付記27)前記アドレス割当手段は、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの大小関係が逆順になるようにすることを特徴とする付記23に記載のプログラムデバッグ装置であっても良い。
(付記28)前記境界検査手段は、前記解析対象メモリアクセスの参照先アドレスから前記基点セグメントの先頭アドレスを減算して得られるオフセットを求め、前記オフセットが前記基点セグメントのサイズから当該参照先アドレスが指定するアドレスの数を減算した値以下であるとき、当該参照先アドレスが前記セグメントに含まれると判定することを特徴とする付記23乃至27のいずれかに記載のプログラムデバッグ装置であっても良い。
(付記29)前記プログラムのセグメントは、ヒープ上に動的に確保されるセグメントであることを特徴とする付記19乃至28のいずれかに記載のプログラムデバッグ装置であっても良い。
(付記30)前記プログラムのセグメントは、前記プログラムの実行時に静的に配置されるセグメントであることを特徴とする付記19乃至28のいずれかに記載のプログラムデバッグ装置であっても良い。
(付記31)前記プログラムのセグメントは、スタック上に配置されるセグメントであることを特徴とする付記19乃至28のいずれかに記載のプログラムデバッグ装置であっても良い。
(付記32)前記プログラムのセグメントは、関数もしくはその関数から呼び出される子関数を含む関数群に対して、一つの関数または関数群内で、スタックポインタを基点とする相対アドレス参照が許可される連続メモリ領域として定義され、前記プログラムの実行中に、関数の呼出が発生した時点で、当該関数に対応するセグメントをスタックポインタと共に異なるアドレスに移動させ、当該関数から呼出元に戻る時点で当該セグメントをスタックポインタと共に元のアドレスに移動させることを特徴とする付記31に記載のプログラムデバッグ装置であっても良い。
(付記33)第1の関数または関数群の実行指令の中で、第2の関数または関数群が呼び出された状態では、第1の関数または関数群に対して定義された前記連続メモリ領域から、第2の関数または関数群に対して定義された前記連続メモリ領域と重複する領域を除去した領域を、第1の関数または関数群に対して定義されたセグメントとすることを特徴とする付記32に記載のプログラムデバッグ装置であっても良い。
(付記34)前記プログラム実行手段は、前記プログラム実行手段が使用するレジスタとメモリとに複数の格納値を記憶させられる仮想実行環境を生成し、前記レジスタと前記メモリとに、前記アドレス割当手段にて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで前記プログラムを実行して参照先アドレスを求めること、または、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記19に記載のプログラムデバッグ装置であっても良い。
(付記35)前記プログラム実行手段は、前記プログラムで使用される変数に、複数の格納値を記憶させられる仮想実行環境を生成し、各々の変数に、前記アドレス割当手段にて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで、前記プログラムを実行して参照先アドレスを求めること、もしくは、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記19に記載のプログラムデバッグ装置であっても良い。
(付記36)本願発明のプログラム変換装置は、第1の情報処理装置がプログラムを実行する時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスの検査処理を第2の情報処理装置に行わせるデバッグ用プログラムを、前記プログラムを変換して生成するプログラム変換装置であって、前記デバッグ用プログラムは、前記記憶領域のアドレスのうち前記セグメントが配置されるアドレスのみを変更して前記セグメントの配置を変更するアドレス割当処理と、前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行処理と、前記アドレス割当処理と前記プログラム実行処理とを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析処理と、前記実行結果解析処理にて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析処理と、を前記第2の情報処理装置に行わせることを特徴とする。
(付記37)本願発明のデバッグ用プログラムは、プログラムの実行時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスをデバッグするデバッグ用プログラムであって、前記記憶領域のアドレスのうち前記セグメントが配置されるアドレスのみを変更して前記セグメントの配置を変更するアドレス割当処理と、前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行処理と、前記アドレス割当処理と前記プログラム実行処理とを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析処理と、前記実行結果解析処理にて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析処理と、をコンピュータに実行させることを特徴とする。
(付記38)前記メモリアクセス解析処理は、前記解析対象メモリアクセスの参照先アドレスに基づいて前記解析対象メモリアクセスにおけるアドレス指定の基点である基点セグメントを特定する基点セグメント特定処理を含み、
前記基点セグメント特定処理が前記基点セグメントを特定できないとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記37に記載のデバッグ用プログラムであっても良い。
(付記39)前記メモリアクセス解析処理は、前記基点セグメント特定処理により特定された前記基点セグメントに前記解析対象メモリアクセスの参照先アドレスが含まれるか否か判定する境界検査処理を含み、前記境界検査処理が、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれると判定するとき、前記解析対象メモリアクセスが適正と判定し、前記解析対象メモリアクセスにおける参照先アドレスが前記セグメントに含まれないと判定するとき、前記解析対象メモリアクセスが適正ではないと判定することを特徴とする付記38に記載のデバッグ用プログラムであっても良い。
(付記40)前記基点セグメント特定処理は、前記解析対象メモリアクセスの参照先アドレスのうち第1の回において参照された第1参照先アドレスと第2の回において参照された第2参照先アドレスの差分が、同一の識別番号が割り当てられたセグメントに対して前記第1の回にて割り当てられた第1先頭アドレスと前記第2の回にて割り当てられた第2先頭アドレスの差分と一致したとき、当該セグメントを前記基点セグメントとして特定することを特徴とする付記39に記載のデバッグ用プログラムであっても良い。
(付記41)前記アドレス割当処理は、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの差分を、前記セグメントを一意の値で与えることを特徴とする付記40に記載のデバッグ用プログラムであっても良い。
(付記42)前記アドレス割当処理は、前記セグメントの配置を変更するとき、前記セグメントのうち第1セグメントと第2セグメントとの変更後の先頭アドレスの差分を変更前の先頭アドレスの差分の整数倍とすることを特徴とする付記40に記載のデバッグ用プログラムであっても良い。
(付記43)前記アドレス割当処理は、前記セグメントの配置を変更するとき、隣接する前記セグメントの間に置かれた空白域の大きさを変更前より変更後の方が一意の値だけ大きくなるように変更することを特徴とする付記40に記載のデバッグ用プログラムであっても良い。
(付記44)前記アドレス割当処理は、前記セグメントの配置を変更するとき、前記セグメントの変更前の先頭アドレスと前記セグメントの変更後の先頭アドレスの大小関係が逆順になるようにすることを特徴とする付記40に記載のデバッグ用プログラムであっても良い。
(付記45)前記境界検査処理は、前記解析対象メモリアクセスの参照先アドレスから前記基点セグメントの先頭アドレスを減算して得られるオフセットを求め、前記オフセットが前記基点セグメントのサイズから当該参照先アドレスが指定するアドレスの数を減算した値以下であるとき、当該参照先アドレスが前記セグメントに含まれると判定することを特徴とする付記40乃至44のいずれかに記載のデバッグ用プログラムであっても良い。
(付記46)前記プログラム実行処理は、前記プログラム実行処理が使用するレジスタとメモリとに複数の格納値を記憶させられる仮想実行環境を生成し、前記レジスタと前記メモリとに、前記アドレス割当処理にて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで前記プログラムを実行して参照先アドレスを求めること、または、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記37に記載のデバッグ用プログラムであっても良い。
(付記47)前記プログラム実行処理は、前記プログラムで使用される変数に、複数の格納値を記憶させられる仮想実行環境を生成し、各々の変数に、前記アドレス割当処理にて変更された前記セグメントの配置に基づいて前記プログラムを実行した場合に得られる複数の格納値を記憶させることで、前記プログラムを実行して参照先アドレスを求めること、もしくは、前記仮想実行環境を用いて前記プログラムを複数回実行する場合に等しく処理して参照先アドレスを得る検査プログラムを生成してこれを実行することで、参照先アドレスを得ることを特徴とする付記37に記載のデバッグ用プログラムであっても良い。
(付記48)本願発明のデバッグ用プログラムは、第1の情報処理装置がプログラムを実行する時にセグメント単位で確保されて使用される記憶領域へのメモリアクセスの検査処理を第2の情報処理装置に行わせるデバッグ用プログラムであって、前記記憶領域のアドレスのうち前記セグメントが配置されるアドレス割当を変更して前記セグメントの配置を変更するアドレス割当処理と、前記セグメントの配置を変更された前記プログラムを実行するとともに前記プログラムの実行に伴ってなされる前記メモリアクセスをトレースして、前記メモリアクセスにより参照された参照先アドレスを得るとともに、前記プログラムが実行された結果を示す実行結果、前記メモリアクセスがなされた回数を示すアクセス回数または前記プログラムに内包される複数の実行指令が実行された順序を示す実行順序の少なくとも一つを得るプログラム実行処理と、前記アドレス割当処理と前記プログラム実行処理とを複数回実行して、得られた複数の前記実行結果、前記アクセス回数または前記実行順序の少なくとも一つが、実行された全ての回において等しいか否かを判定する実行結果解析処理と、前記実行結果解析処理にて実行された全ての回において等しいと判定されたとき、複数の前記実行指令のうち解析対象の実行指令に従ってなされた解析対象メモリアクセスの前記参照先アドレスを解析して、解析対象メモリアクセスが適正であるか否か判定するメモリアクセス解析処理と、を前記第2の情報処理装置に行わせることを特徴とする。
この出願は、2007年12月12日に出願された日本出願特願2007−320278を基礎とする優先権を主張し、その開示の全てをここに取り込む。