JP2009237610A - コード変換装置及びコード変換方法 - Google Patents

コード変換装置及びコード変換方法 Download PDF

Info

Publication number
JP2009237610A
JP2009237610A JP2008079220A JP2008079220A JP2009237610A JP 2009237610 A JP2009237610 A JP 2009237610A JP 2008079220 A JP2008079220 A JP 2008079220A JP 2008079220 A JP2008079220 A JP 2008079220A JP 2009237610 A JP2009237610 A JP 2009237610A
Authority
JP
Japan
Prior art keywords
code
hook
hook point
address
point
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
JP2008079220A
Other languages
English (en)
Inventor
Hiroshi Fujimoto
拓 藤本
Kazuhisa Sekine
和寿 関根
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.)
NTT Docomo Inc
Original Assignee
NTT Docomo Inc
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 NTT Docomo Inc filed Critical NTT Docomo Inc
Priority to JP2008079220A priority Critical patent/JP2009237610A/ja
Publication of JP2009237610A publication Critical patent/JP2009237610A/ja
Pending legal-status Critical Current

Links

Images

Landscapes

  • Debugging And Monitoring (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

【課題】フックポイントにフックコードを埋め込むフックコード埋め込み方式のトレース技術を用いる場合において、ソースコードに改変せずに、オーバヘッドを抑えたプログラム実行のトレースを実現するコード変換装置及びコード変換方法を提供する。
【解決手段】コード変換装置100は、フックポイント検出情報400を出力するフックポイント検出部110と、第2のコード300を生成する第2のコード生成部120と、第2のコード300が配置されるプロセス空間500上のアドレスを特定するアドレス特定部130と、フックポイント検出情報400によって特定されるフックポイントから、アドレスが特定されたコードを第2のコード300へ分岐するために用いられるフックコードとした場合において、置換コードをフックコードに置き換えるコード変換部140と、変換済み第1のコード210、第2のコード300及びフックポイント検出情報400を出力する出力部150とを備える。
【選択図】図3

Description

本発明は、プログラムのトレース方式に関し、特に、プログラムのトレースにおいて、第1のコードのプロセス空間上に第2のコードを配置するために、前記第1のコードを変換するコード変換装置及びコード変換方法に関する。
プログラムに発生する不具合原因の特定や、プログラムの性能改善を行うため、プログラムの動作をトレースし、トレース結果(以下、トレースログ)を取得する技術がある。トレース技術は、使用用途、トレース手段、或いは取得するトレースログなどによって様々な種類がある。
図1は、プログラムトレースの原理を説明する説明図である。図1に示すように、何れのトレース技術も、基本的には以下のようなステップを実行することによって、ターゲットプログラムのトレースを実現する。
(1) ターゲットプログラムを追跡するトレースコードを用意する
(2) ターゲットプログラムからトレースコードを呼び出すフックのアドレス(フックポイント)やタイミングを設定する
(3) ターゲットプログラムの実行中、フックによりトレースコードが呼び出された際、トレースコードによって、呼び出された時点におけるプログラムの状況をトレースログとして記録する
トレース技術は、上述したような「フック」をいかにして実現するかによって、取得可能なトレースログや使用条件が異なる。トレース技術は、フックの実現手段によって以下のように分類できる。
(1) サンプリング方式
(2) フックコード埋め込み方式
・ 動的変換型
・ ソース埋め込み型
サンプリング方式は、ターゲットプログラムの実行中に、トレーサが一定間隔でシグナルを発生することによって、ターゲットプログラムの動作を停止させる。プロセスを停止させる性質上、トレーサ自体は、システム上において高い権限を持ったプロセス(親プロセスやカーネル権限プロセス)によって実現される。代表的なサンプリング方式のトレーサには、sysprof(非特許文献1参照)やoprofile(非特許文献2参照)がある。
サンプリング方式は、主にプログラム性能のプロファイリングに用いられる。例えば、プログラムの動作中に一定間隔でプログラムカウンタをサンプリングすることによって、ターゲットプログラムが実行中であるアドレスが取得されていく。このため、ターゲットプログラム中のどのルーチンがより多く実行されているかを把握でき、性能改善のポイントを特定できる。また、サンプリング方式は、動作中の任意のプロセスに対してアタッチできる特徴がある。
サンプリング方式の欠点は、プログラムの特定部分をフックすることができないことである。例えば、トレースログにおける有用なログの一つとして、関数コールの履歴(コールグラフ)が挙げられる。しかし、サンプリング方式は、関数コールのentryやreturn部分を確実にフックできる保証がない。また、極端に実行時間や実行回数が少ない関数については、サンプリング自体が行われない可能性もある。このため、関数の呼び出し履歴、関数間の関係、関数の引数や返り値といったコンテキスト情報を取得することは非常に困難である。
一方、フックコード埋め込み方式は、ターゲットプログラム中に直接フックコードを埋め込む。フックコードは、プロセス空間内をジャンプする分岐命令や、カーネルへ処理を移すソフトウェア割り込みである。
フックコード埋め込み方式は、フックコードやフックコード埋め込み手段によって、さらに動的変換型またはソース埋め込み型に分類される。
動的変換型は、ターゲットプログラム実行時に、当該ターゲットプログラムのコード領域を書き換えることによってフックコードを埋め込む。例えば、GDB(非特許文献3参照)は、ターゲットプログラムを子プロセスとして実行し、ptraceシステムコールを利用することによって子プロセスのコードへフックコードを埋め込む。フックコードが実行されると、親プロセス(GDB)へ制御が戻る。親プロセスに制御が戻った時点での子プロセスのメモリへアクセスすることによって、様々なトレースログを取得可能である。フックコードは、任意のアドレスへ埋め込むことが可能であるため、コールグラフを含め、任意のタイミングでターゲットプログラムからコンテキスト情報を取得可能である。
また、DTrace(非特許文献4参照)は、ターゲットプログラムの動作中に当該プロセスのメモリ空間へ直接アタッチし、フックコードとしてソフトウェアブレイク命令を埋め込む。実際にフックコードが実行されれば、DTrace(カーネルプロセス)へのコンテキストスイッチが行われ、当該時点におけるメモリにアクセスすることによって、様々なトレースログを取得する。
動的変換型の欠点は、実行時の実行時間オーバヘッドである。ターゲットプログラムがフックコードを呼び出すことによって、トレーサへのコンテキストスイッチが発生するためである。また、トレーサがターゲットプログラムのコンテキストを復元する際には、トレーサは、次のフックポイントを探索してフックコードを埋め込む必要があり、プログラムの実行中におけるコードの解析や変換によるオーバヘッドも大きい。
ソース埋め込み型には、gprof(非特許文献5参照)、CTrace(非特許文献6参照)、及びetrace(非特許文献7参照)などがある。gprofは、全ての関数のentryにCのライブラリ関数であるmcount(・)関数を埋め込み、関数呼び出しが発生した時点でのアドレスを記録していく。このため、ターゲットプログラムの実行中に呼び出された全ての関数について、コールグラフを取得できる。
CTraceは、ターゲットプログラムのソースコードに改変を加えることによって、ソースレベルにおいてフックコードとトレースコードとを埋め込む。フックコードは、トレースコード中のルーチンを呼び出すための分岐命令となる。改変されたターゲットプログラムは再コンパイルされ、実行される。このような処理によって、フックコードが実行される毎にトレースコードが実行され、実行時点におけるコンテキスト情報を取得できる。
さらに、フックコードは、プログラムソース中の任意の位置に埋め込むことができるため、ターゲットプログラムを任意のタイミングでフックできる。
etraceは、ターゲットプログラムにトレースコードを埋め込んだのち、GNU C Compiler(gcc)の拡張コンパイルオプションである”-finstruments-functions”を用いて、ターゲットプログラムを再コンパイルする。当該コンパイルオプションは、全ての関数entryとreturnとによって任意のコードを実行させることを可能とする。このため、関数のentryとreturnとによって、埋め込んだトレースコードを呼び出すことができ、コールグラフや引数など、実行時点における様々なコンテキスト情報を取得できる。
ソース埋め込み型の欠点は、ターゲットプログラムのソースが必要となる点である。プログラムの開発中にデバッグ目的で使用するのであれば、ソースコードも入手できるが、ターゲットプログラムがリリースされた後、開発者以外のユーザが当該ターゲットプログラムを用いている場合、ソースコードが入手できない場合も多く利用しにくい。また、フックコードが恒久的にターゲットプログラムに埋め込まれてしまうため、当該ターゲットプログラムについて恒常的なオーバヘッドが発生する。例えば、必要な時にだけトレースログを取得するといった、選択的なトレースを行うことはできない。
表1は、上述したトレース技術(トレーサ)の特徴を示す。
Figure 2009237610
Sysprof、[online]、[平成20年3月6日検索]、<URL: http://www.daimi.au.dk/~sandmann/sysprof/> Oprofile、[online]、[平成20年3月6日検索]、<URL: http://oprofile.sourceforge.net/news/> GDB、[online]、[平成20年3月6日検索]、<URL: http://sourceware.org/gdb/> Dtrace、[online]、[平成20年3月6日検索]、<URL: http://jp.sun.com/products/software/solaris/10/dtracehowto.html> gprof、[online]、[平成20年3月6日検索]、<URL: http://www.cs.utah.edu/dept/old/texinfo/as/gprof_toc.html> Ctrace、[online]、[平成20年3月6日検索]、<URL: http://ctrace.sourceforge.net/>
しかし、上述した従来のトレース技術には、次のような問題があった。すなわち、リリースされたソフトウェアをユーザが実際に利用する際に、当該ソフトウェアをトレースする場合、上述した従来のトレース技術は必ずしも有用でない問題があった。
例えば、新規に開発されたソフトウェアは、開発時にプログラムに混入したバグによって不具合が発生する可能性が高い。このような場合、当該ソフトウェアをトレースし、トレースコードによって不具合の診断に有用なトレースログを取得すること考えられる。このようなトレースログとして最も広く用いられているのが、ソフトウェアに致命的な障害が発生した場合などに、OSの機能によって出力されるメモリダンプである。
メモリダンプは、強制終了時におけるメモリの内容がそのまま出力されるため、不具合の発生箇所や、スタックトレースによって障害発生直前のコンテキスト情報を取得できる。しかし、メモリダンプには、障害発生直前の情報しか保存されていないため、障害に至るまでのコンテキスト情報を時系列で遡り、根本原因を特定することは困難である。また、強制終了に至らない過渡的な障害に対しては有用でない。
一方、プログラム開発時には、上述したような多数のプロファイラやデバッガによって、メモリダンプ以外のコンテキスト情報(関数のコールグラフや引数、返り値、或いはデータの入出力に関する情報)が用いられる。このようなコンテキスト情報は、メモリダンプの情報と合わせて、バグの発見や不具合の修正に活用されている。
そこで、開発時だけではなく、ソフトウェアのリリース後においても、このようなコンテキスト情報を随時取得しておくことによって、当該ソフトウェアに対する事後のサポートやアップデートに活用できると考えられる。図2は、メモリダンプとコンテキスト情報との関係を示す。
すなわち、上述したような既存のトレース方式は、ソースコードに改変せずに、オーバヘッドを抑えつつプログラムの実行をトレースすることはできない問題があった。つまり、ユーザが用いるソフトウェアのトレース方式として適当ではない問題があった。
そこで、本発明は、このような状況に鑑みてなされたものであり、フックポイントにフックコードを埋め込むフックコード埋め込み方式のトレース技術を用いる場合において、ソースコードに改変せずに、オーバヘッドを抑えたプログラム実行のトレースを実現するコード変換装置及びコード変換方法を提供することを目的とする。
上述した問題を解決するため、本発明は、次のような特徴を有している。まず、本発明の第1の特徴は、入力された第1のコード(第1のコード200)のプロセス空間(プロセス空間500)上に第2のコード(第2のコード300)を配置するために、前記第1のコードを変換するコード変換装置(コード変換装置100)であって、あらかじめ与えられた規則(フックポイント検出規則600)に従い、前記第1のコードから前記第2のコードを呼び出すポイントをフックポイント(フックポイントHP)に設定するとともに、前記フックポイント上のコードを置換コードとした場合において、前記第1のコードの中から前記フックポイントを検出し、前記フックポイントのアドレス及び前記置換コードをフックポイント検出情報(フックポイント検出情報400)として出力するフックポイント検出部(フックポイント検出部110)と、前記第2のコードを生成する第2のコード生成部(第2のコード生成部120)と、前記第2のコード生成部によって生成された前記第2のコードが配置される前記プロセス空間上のアドレスを特定するアドレス特定部(アドレス特定部130)と、前記フックポイント検出情報によって特定される前記フックポイントから、前記アドレス特定部によって前記アドレスが特定されたコードを前記第2のコードへ分岐するために用いられるフックコードとした場合において、前記置換コードを前記フックコードに置き換えるコード変換部(コード変換部140)と、前記コード変換部によって変換された変換済み第1のコード(変換済み第1のコード210)、前記第2のコード及び前記フックポイント検出情報を出力する出力部(出力部150)とを備え、前記第2のコード生成部によって生成される前記第2のコードは、前記第1のコードから前記第2のコードを呼び出す前記フックポイントを特定するフックポイント特定処理と、前記フックポイント検出情報を参照し、前記フックポイントに対応する前記置換コードを実行する置換コード実行処理と、コードの実行制御を前記フックポイントへ復帰させる復帰処理とを含むことを要旨とする。
本発明の第2の特徴は、本発明の第1の特徴に係り、前記フックポイントは、複数設定されており、前記第2のコード生成部は、前記第2のコード上に、それぞれの前記フックポイントに対応するエントリポイントを用意し、前記フックコードは、前記エントリポイントへの分岐命令であり、前記フックポイント特定処理は、前記エントリポイントに基づいて前記フックポイントを特定することを要旨とする。
本発明の第3の特徴は、本発明の第1の特徴に係り、前記フックポイント特定処理は、前記置換コードが関数を呼び出す分岐命令であった場合、前記関数の呼び出しに対する返りアドレスを参照することによって前記フックポイントを特定することを要旨とする。
本発明の第4の特徴は、本発明の第1の特徴に係り、前記アドレス特定部は、前記第1のコードのコード領域と、前記第1のコードのデータ領域との間に未使用のメモリ領域が存在し、かつ前記メモリ領域のサイズが前記第2のコードのサイズより大きい場合、前記メモリ領域に前記第2のコードを配置することを要旨とする。
本発明の第5の特徴は、本発明の第1の特徴に係り、前記アドレス特定部は、前記第1のコードの実行開始時にローダによる共有ライブラリのロード処理が実行される場合、前記ロード処理の開始前に前記ロード処理をフックし、前記第2のコードを前記共有ライブラリとして前記プロセス空間上に配置することを要旨とする。
本発明の第6の特徴は、本発明の第1の特徴に係り、前記アドレス特定部は、前記第1のコードと対応する仮想アドレス空間のうち、共有ライブラリとして前記第2のコードを配置可能な配置可能アドレスを特定し、前記第2のコード生成部は、前記配置可能アドレスをアドレス情報として前記第2のコードに含め、前記出力部は、前記第1のコードの実行開始時に、前記アドレス情報を前記共有ライブラリのロード処理に提供することによって、前記第2のコードを前記共有ライブラリとして前記プロセス空間上に配置することを要旨とする。
本発明の第7の特徴は、本発明の第5の特徴に係り、前記コード変換部は、前記フックポイント検出部によって検出された前記フックポイントのうち、前記フックコードを挿入するためのコード変換規則が特定のフックポイントにのみ与えられた場合、前記コード変換規則によって指定された前記フックポイントにのみ、前記フックコードを埋め込むことを要旨とする。
本発明の第8の特徴は、本発明の第1の特徴に係り、前記第2のコード生成部が生成する前記第2のコードは、前記フックポイント特定処理、前記置換コード実行処理、及び前記復帰処理に加え、前記第1のコードの実行終了時に呼び出されて実行される実行後処理を含むことを要旨とする。
本発明の第9の特徴は、前記フックポイント検出部は、前記第1のコードの中から最後に実行される前記フックポイントを検出し、前記コード変換部は、最後に実行される前記フックポイントに、前記第2のコードの前記実行後処理を呼び出す前記フックコードを挿入することを要旨とする。
本発明の第10の特徴は、入力された第1のコードのプロセス空間上に第2のコードを配置するために、前記第1のコードを変換するコード変換方法であって、あらかじめ与えられた規則に従い、前記第1のコードから前記第2のコードを呼び出すポイントをフックポイントに設定するとともに、前記フックポイント上のコードを置換コードとした場合において、前記第1のコードの中から前記フックポイントを検出し、前記フックポイントのアドレス及び前記置換コードをフックポイント検出情報として出力するステップと、
前記第2のコードを生成するステップと、生成された前記第2のコードが配置される前記プロセス空間上のアドレスを特定するステップと、前記フックポイント検出情報によって特定される前記フックポイントから、前記アドレスが特定されたコードを前記第2のコードへ分岐するために用いられるフックコードとした場合において、前記置換コードを前記フックコードに置き換えるステップと、前記置き換えるステップにおいて変換された変換済み第1のコード、前記第2のコード及び前記フックポイント検出情報を出力すステップとを備え、前記生成するステップにおいて生成される前記第2のコードは、前記第1のコードから前記第2のコードを呼び出す前記フックポイントを特定し、前記フックポイント検出情報を参照し、前記フックポイントに対応する前記置換コードを実行し、コードの実行制御を前記フックポイントへ復帰させることを要旨とする。
本発明の特徴によれば、フックポイントにフックコードを埋め込むフックコード埋め込み方式のトレース技術を用いる場合において、ソースコードに改変せずに、オーバヘッドを抑えたプログラム実行のトレースを実現するコード変換装置及びコード変換方法を提供することができる。
次に、本発明の実施形態について説明する。具体的には、本発明の第1実施形態〜第3実施形態について説明する。
なお、以下の図面の記載において、同一または類似の部分には、同一または類似の符号を付している。ただし、図面は模式的なものであり、各寸法の比率などは現実のものとは異なることに留意すべきである。
したがって、具体的な寸法などは以下の説明を参酌して判断すべきものである。また、図面相互間においても互いの寸法の関係や比率が異なる部分が含まれていることは勿論である。
[第1実施形態]
まず、本発明の第1実施形態について説明する。具体的には、(1)コード変換装置の全体概略構成、(2)各ブロックの機能、(3)コード変換装置の動作、及び(4)作用・効果について説明する。
(1)コード変換装置の全体概略構成
図3は、本実施形態に係るコード変換装置100の全体概略構成図である。図3に示すように、コード変換装置100は、フックポイント検出部110、第2のコード生成部120、アドレス特定部130、コード変換部140及び出力部150を備える。
コード変換装置100は、入力された第1のコード200を変換し、変換済み第1のコード210を出力する。このような変換は、例えば、ターゲットプログラムのバイナリコードを第1のコード200とし、トレースコードを第2のコード300とした場合、第1のコード200を第2のコード300によってトレースするために行われる。
すなわち、コード変換装置100は、入力された第1のコード200のプロセス空間500上に第2のコード300を配置するために、第1のコード200を変換する機能を有する。
本実施形態に係るトレースは、少なくとも3つの特徴を有する。第1の特徴は、第1のコード200中のトレース対象アドレスをフックポイントHP(図3において不図示、図4参照)とすることである。つまり、フックポイントHPにフックコードを埋め込むことによって、第2のコード300を呼び出すフックコード埋め込み方式である。フックコード埋め込み方式は、フックポイントHPにおいて確実に第1のコード200から第2のコード300を呼び出すことができるため、ソフトウェアの不具合診断に用いられるトレースログの取得など、確実に特定のポイントをトレースしたい場合に有用である。
第2の特徴は、ターゲットプログラムのソースを一切改変しないことである。改変しない理由は、特定のソフトウェアがリリースされた後に当該ソフトウェアのプログラムコードをトレースする場合、ソースコードが入手困難であることが想定されるためである。
第3の特徴は、低いオーバヘッドを実現するため、第1のコード200と第2のコード300を同一のプロセス空間500に配置する。さらに、第1のコード200の実行開始後には、第1のコード200に対する動的変換処理、つまり、ターゲットプログラム実行中におけるフックポイントHPの検出やフックコードへの変換及び挿入といった処理を行わない。
なお、第1のコード200中からフックポイントHPをどのように検出するかについては、実際のトレース処理に依存する。本実施形態では、何らかの手段によってトレース対象のポイントは特定可能であるものとする。例えば、関数callグラフをトレースログとして記録する場合、関数呼び出し用の決まったコードを検出すればよい。また、さらにトレースポイントを限定する方法としては、例えば、特開2001-34503号公報に記載されている方法を用いることができる。具体的には、当該公報では、あらかじめ取得したトレース情報を解析することによって、次回解析時のトレースポイントを必要部分に限定する方法が記載されている。
(2)各ブロックの機能
次に、コード変換装置100を構成する各ブロックの機能について説明する。
(2.1)フックポイント検出部110
フックポイント検出部110は、あらかじめ与えられたフックポイント検出規則600に従い、第1のコード200から第2のコード300を呼び出すポイントをフックポイントHPに設定する。また、フックポイント検出部110は、フックポイントHP上のコードを置換コードとした場合において、第1のコード200の中からフックポイントHPを検出し、フックポイントHPのアドレス及び置換コードをフックポイント検出情報400として出力する。
具体的には、フックポイント検出部110は、第1のコード200及びフックポイント検出規則600を入力とし、フックポイント検出規則600に従って、第1のコード200中に存在するフックポイントHPのアドレスを検出する。
また、フックポイント検出部110は、第1のコード200の中から最後に実行されるフックポイントHPを検出することができる。
本実施形態では、第1のコード200は、コンパイル済みの実行可能バイナリである。フックポイント検出部110による処理は、第1のコード200の実行開始前における任意の時点で行うことができる。
例えば、第2のコード300によって関数呼び出しを記録していくようなトレースを考える。このような場合、フックポイントHPは、関数呼び出しの命令が存在するアドレスとなる。フックポイント検出部110は、まず第1のコード200を逆アセンブルし、逆アセンブルの結果を全て探索することによって、関数呼び出しに該当する命令を検出する。このような命令は、第1のコード200がどのようなCPUアーキテクチャ向けにコンパイルされているかにより異なる。例えば、ARM(Acorn RISC Machine)の場合は、次の3つの命令が関数呼び出し命令の可能性がある。つまり、フックポイント検出規則600は、当該3つの命令を検出対象として指定する。
・ bl <address>
・ mov pc <Rd>(pcはプログラムカウンタ、Rdは汎用レジスタを表す)
・ ldr pc <address>(<address>は、適当なアドレス表現を表す)
bl命令は、lrレジスタ(関数呼び出し後の帰還アドレス格納レジスタ)へ現在のアドレスを格納した上で<address>へ分岐する関数呼び出し用分岐命令である。
mov pcやldr pcは、それぞれ汎用レジスタに格納されたアドレス、或いは<address>で示されたアドレスの値をプログラムカウンタにセットすることによって、当該アドレスへ分岐する分岐命令を表す。以下の説明では、これらのフックポイントHP上の命令を置換コードと呼ぶ。
フックポイント検出部110は、これらの命令が存在するアドレスと置換コードとを、フックポイント検出情報400として出力する。表2は、フックポイント検出情報400の例を示す。
Figure 2009237610
(2.2)第2のコード生成部120
第2のコード生成部120は、第1のコード200から呼び出される第2のコード300を生成する。第2のコード300の生成は、第1のコード200の実行開始前における任意の時点で行うことができる。また、フックポイント検出部110による処理と独立して行うことができる。
上述したように、第2のコード300は、第1のコード200をトレースするトレースコードである。第2のコード生成部120によって生成される第2のコード300は、第1のコード200から呼び出された際にトレース処理を実行する以外に、第1のコード200から第2のコード300を呼び出すフックポイントHPを特定するフックポイント特定処理と、フックポイント検出情報400を参照し、フックポイントHPに対応する置換コードを実行する置換コード実行処理と、コード、具体的には第1のコード200の実行制御をフックポイントHPへ復帰させる第1のコード復帰処理とを有する。以下、図4を参照しながら各処理の内容について説明する。図4は、本実施形態において用いられるコードの概略構成を示す。
(2.2.1)トレース処理
トレース処理は、第2のコード300を用いてどのようなトレースを実現したいかによって内容が異なる。例えば、ARMにおいて関数呼び出しと、当該関数の引数を記録していくような場合、置換コードの分岐先アドレス、及び汎用レジスタのr1からr5を記録する。なぜなら、置換コードは、関数呼び出し分岐命令そのものであり、当該分岐命令の分岐先アドレスは、呼び出される関数のアドレスを示すためである。また、ARMでは、関数呼び出しの際、上位5つの引数については、汎用レジスタのr1からr5に格納される特徴があるためである。
このようなトレースログを二次記憶装置などの低速なデバイスへ随時出力すると、高いオーバヘッドが発生する。そこで、本実施形態では、メモリ容量に余裕がある限り、当該メモリ上の適当なバッファに蓄積していくものとする。
(2.2.2)フックポイント特定処理
フックポイント特定処理は、トレース処理に先んじて呼び出され、第1のコード200上の呼び出し元フックポイントを特定する。後述のように、フックポイントHP上の置換コードは、第2のコード300を呼び出すためのフックコードに置き換えられる。フックコードは、通常の分岐命令であり、分岐先から単純に分岐元のアドレスを特定することができない。
一方、第2のコード300のトレース処理を実行後には、フックコードに置き換えられた置換コードが実行された上で、元のフックポイントHPへ実行制御が復帰し、第1のコード200の実行が再開される必要がある。このため、分岐元のフックポイントHPを特定するフックポイント特定処理が必要となる。
分岐元のフックポイントHPを特定する方法の一つとして、フックポイントHP毎に第2のコード300上にエントリポイントを用意する方法が考えられる。図4に示す例では、ha, hb,…, hzは、フックポイントHPのアドレスである。すなわち、フックポイントHPは、複数設定されている。また、A, B,…, Zは、置換コードである。
この場合、フックポイント検出情報400は、(ha、A), (hb、B),…といったように、フックポイントHPのアドレスと置換コードとがセットで記録される。各置換コードは、後述するコード変換部140によってフックコードa, b,…, zに置き換えられる。各フックコードは、フックポイントHP特定処理上のエントリポイントa’, b’,…, z’へ分岐する分岐命令である。各エントリポイントとフックポイントHPとが一意に対応するため、フックポイント特定処理は、分岐先のエントリポイントに応じて分岐元のフックポイントHPを特定できる。
すなわち、本実施形態では、第2のコード生成部120は、第2のコード300上に、それぞれのフックポイントHPに対応するエントリポイントを用意する。
なお、上述したような関数呼び出しをトレースする例においては、別の手段でフックポイントHPを特定することが可能である。このような場合、置換コードは関数呼び出し命令であり、置換コードが実行される前には必ず、関数実行後の帰還アドレス(すなわちフックポイントHPのアドレスが専用レジスタに登録される。ARMの場合、lrレジスタが専用レジスタに該当する。
このため、このようなトレースを行う場合に限り、フックポイント特定処理は、当該レジスタを参照することによって、簡単に呼び出し元フックポイントのアドレスを特定できる。つまり、フックポイント特定処理は、置換コードが関数を呼び出す分岐命令であった場合、当該関数の呼び出しに対する帰還アドレス(返りアドレス)を参照することによって呼び出し元フックポイントを特定する。
(2.2.3)置換コード実行処理
置換コード実行処理は、トレース処理実行後に呼び出され、フックコードによって置き換えられた置換コードを実行する。置換コードは、第1のコード200上で元々実行されるはずだった処理であるため、第1のコード200へ実行制御が復帰する前に必ず実行される必要がある。
フックポイントHPが特定できている場合、フックポイント検出情報400に基づいて対応する置換コードが特定できる。例えば、エントリポイントa’が呼び出されていた場合、エントリポイントのアドレスはhaであるため、置換コードはAと特定され、Aが実行される。
(2.2.4)第1のコード復帰処理
第1のコード復帰処理は、第1のコード200のフックポイントHPへ復帰する処理である。第1のコード復帰処理によって、第1のコード200の実行が再開される。
フックポイントHPのアドレスは、フックポイント特定処理によって特定されている。例えば、エントリポイントa’が呼び出されていた場合には、アドレスhaへ復帰する。
なお、上述した関数呼び出しのトレースのように、置換コードが分岐命令である場合には、第1のコード復帰処理は実行されない場合もある。この場合、置換コードが関数呼び出しの分岐命令であるため、置換コード実行処理による置換コードが実行されると、第1のコード200上で実行されるはずであった関数呼び出しが実行され、第1のコード200へ実行制御が復帰するからである。
(2.2.5)実行後処理
図4に示すように、第2のコード生成部120が生成する第2のコード300は、第1のコード200の実行終了時に呼び出されて実行される実行後処理を含むようにしてもよい。
実行後処理は、上述したようなトレースログを取得する場合において必要である。上述したように、関数呼び出し時に取得されていくトレースログは、メモリ上のバッファに一時的に蓄積することが好ましい。
第2のコード300がバッファ領域を取得するためには、heapを利用すればよい。しかし、メモリ上のバッファは、第1のコード200の実行終了時点で消去されてしまうため、第1のコード200の実行終了直前に、バッファに残ったトレースログを全て書き出す必要がある。具体的には、最後に実行されるフックポイントHPのみ、トレース処理実行後に特別な実行後処理を実行すればよい。
例えば、ELFバイナリの場合、プログラムが正常終了する限り、.finiセグメントが必ず最後に実行される。そこで、.finiセグメントに存在するフックポイントHPのうち、最も下位のフックポイントHPから第2のコード300が呼び出された場合にのみ、第2のコード300のトレース処理は、実行後処理を呼び出し、全てのトレースログを二次記憶装置などに書き出す。このような処理によって、第1のコード200が終了するまで取得された全てのトレースログを欠損なく取得できる。
(2.3)アドレス特定部130
アドレス特定部130は、第2のコード生成部120によって生成された第2のコード300が配置されるプロセス空間500上のアドレスを特定する。具体的には、アドレス特定部130は、第2のコード300を入力とし、第2のコード300が配置されるアドレスを特定する。
本実施形態では、第1のコード200から第2のコード300が呼び出される際に、コンテキストスイッチが発生することを抑えるため、両コードは、同一のプロセス空間500に配置される。本実施形態に係るアドレス特定部130は、第2のコード300が配置されるプロセス空間500上のアドレスを特定するだけではなく、第1のコード200中の空き領域に第2のコード300を埋め込む。
具体的には、アドレス特定部130は、第1のコード200のコード領域と、第1のコード200のデータ領域との間に未使用のメモリ領域が存在し、かつ当該メモリ領域のサイズが第2のコード300のサイズより大きい場合、当該メモリ領域に第2のコード300を配置する。当該処理は、第2のコード生成部120による第2のコード300の生成終了後、第1のコード200実行前における任意の時点で行うことができる。第2のコード300は実行可能バイナリであるため、少なくとも第1のコード200の実行可能領域(.textなどの配置領域)に配置される必要がある。図5は、第1のコード200がELFバイナリである場合におけるプログラムヘッダの例を示す。
図5に示すように、PHDRは、プログラムヘッダが配置されるアドレスを示す。INTERPは、共有ライブラリのロード処理など、プログラム実行開始前に呼び出されるインタプリタ処理を示す。
2つ存在するLOADのうち、FlagがRE(読み、実行可能領域)であるLOADは、.textなどの実行可能コードが配置される領域である。一方、FlagがRW(読み、書き可能)であるLOADは、.dataなどのデータが配置される領域である。
仮にFlagがRE(読み、実行可能領域)であるLOADをLOAD1、FlagがRW(読み、書き可能)であるLOADをLOAD2とした場合、第2のコード300は実行可能領域に配置される必要があるため、LOAD1(図中のA1枠部分)に配置される必要がある。
図6は、第2のコード300が配置可能な領域を示す。LOAD1の末尾、かつLOAD2と重複しない領域に配置される必要がある。図6では、アドレス0x8907からアドレス0x1098の領域である。当該領域を超過して第2のコード300が配置された場合、実際に第1のコード200が実行された際に、LOAD2のロードによって第2のコード300が破壊される可能性がある。
なお、全ての関数呼び出しと、引数とを記録する第2のコード300を実装し、第1のコード200としてgzipに対して適用した場合、gzipの空き領域33[KB]に対して、27[KB]の第2のコード300を記述可能であることが確認されている。
(2.4)コード変換部140
コード変換部140は、フックポイント検出情報400400に基づいて、第1のコード200にフックコードを埋め込んでいく処理を実行する。具体的には、コード変換部140は、第2のコード300が配置されるプロセス空間500上のアドレスが特定されたコードを、フックポイント検出情報400によって特定されるフックポイントHPから第2のコード300へ分岐するために用いられるフックコードとする。さらに、コード変換部140は、置換コード、つまり、フックポイントHP上の命令を当該フックコードに置き換える。
フックコードを埋め込むアドレスは、フックポイント検出情報400によって特定される。また、フックコードは分岐命令であるが、分岐先のアドレスは、アドレス特定部130によって特定されている。
コード変換部140は、フックポイント検出情報400によって示されたアドレスに、第2のコード300のアドレスへ分岐する分岐命令を上書きしていく。置換コードは既にフックポイント検出情報400として退避されているため、上書きしていくことで失われる情報はない。また、第2のコード300のフックポイント特定処理がフックポイントHP毎にエントリポイントを用意する場合には、フックコードの分岐先はそれぞれ対応するエントリポイントになる。
コード変換部140は、上述したコード変換を実行後、変換済み第1のコード210を出力部150に出力する。なお、コード変換部140による処理は、フックポイント検出部110またはアドレス特定部130のよる処理終了後、或いは第1のコード200における実行前の任意の時点で行うことができる。
また、コード変換部140は、第1のコード200を実行した結果、最後に実行されるフックポイントHPに、上述した実行後処理を呼び出すフックコードを挿入することができる。
(2.5)出力部150
出力部150は、単純に第2のコード300が配置された変換済み第1のコード210、及びフックポイント検出情報400を出力するのみである。つまり、出力部150は、変換済み第1のコード210、第2のコード300及びフックポイント検出情報400を出力ことができる。
実際に第1のコード200が実行された際には、フックポイントHPから自動的に第2のコード300が呼び出されてトレース処理が実行される。この際、第2のコード300は、フックポイント検出情報400を参照することによって必要な処理を行うことができる。
(3)コード変換装置の動作
次に、コード変換装置100の動作について説明する。図7は、コード変換装置100を構成する各ブロックの動作フローを示す。
図7に示す全ての処理は、第1のコード200の実行前に静的に行うことできる。つまり、動的変換処理に係わるオーバヘッドは一切発生せず、第2のコード300の実行に伴うオーバヘッドが加わるのみである。
ステップS10において、第1のコード200がフックポイント検出部110に入力される。
ステップS20において、フックポイント検出部110は、入力された第1のコード200の内容を解析する。具体的には、フックポイント検出部110は、第1のコード200の中からフックポイントHPを検出する。
ステップS30において、フックポイント検出部110は、検出したフックポイントHPのアドレス及び置換コードを含むフックポイント検出情報400をコード変換部140に出力する。
ステップS40において、第2のコード生成部120は、第2のコード300を生成する。
ステップS50において、第2のコード生成部120は、生成した第2のコード300をアドレス特定部130に出力する。
ステップS60において、アドレス特定部130は、第2のコード生成部120から出力された第2のコード300が配置されるプロセス空間500上のアドレスを特定する。また、アドレス特定部130は、特定したアドレスに第2のコード300を配置する。
ステップS70において、アドレス特定部130は、特定したアドレスに第2のコード300が配置された第1のコード200をコード変換部140に出力する。
ステップS80において、コード変換部140は、フックポイント検出部110から出力されたフックポイント検出情報400に含まれるフックポイントHP及び置換コードに基づいて、アドレス特定部130から出力された第1のコード200にフックコードを埋め込む。
ステップS90において、コード変換部140は、フックコードを埋め込むことによって変換された変換済み第1のコード210を出力部150に出力する。
(4)作用・効果
本実施形態に係るコード変換装置100によれば、フックポイント検出部110は、トレースする内容により特定される規則(フックポイント検出規則600)に従い、第1のコード200からフックポイントHPを検出する。例えば、第1のコード200全ての関数呼び出しをトレースしたい場合には、フックポイントHPは関数呼び出しを実行する分岐命令である。フックポイント検出部110は、第1のコード200から該当する全て分岐命令を検出する。検出したフックポイントHPのアドレスは、フックポイントHPのアドレスとともに、フックポイント検出情報400として、出力する。
第2のコード生成部120は、第2のコード300、つまり、トレースコードを生成する。第2のコード300の生成は、フックポイント検出部110の処理とは独立に行われる。第2のコード300は、第1のコード200をトレースする以外に、フックポイント特定処理と、置換コード実行処理と、第1のコード復帰処理とを有する。当該3つの処理によって、第2のコード300がフックコードから呼び出されて実行された場合であっても、フックコードに置き換えられた置換コードが実行される。さらに、フックポイントHPへコードの実行制御を復帰させ、フックポイントHPから第1のコード200の実行を再開させることができる。
アドレス特定部130は、第2のコード300が配置されるアドレスを特定する。第1のコード200から第2のコード300が呼び出される際、両者が同一プロセス空間にない場合には、コンテキストスイッチが発生する。そこで、第2のコード300は、第1のコード200の実行に影響を及ぼさないように、第1のコード200が実行されるプロセス空間500の適当なアドレスに配置される必要がある。アドレス特定部130は、当該アドレスを特定する。
コード変換部140は、置換コードを、アドレス特定部130によってアドレスが特定された第2のコード300を呼び出すためのフックコードへと置き換える。フックコードによって第1のコード200のフックポイントHPから第2のコード300へと分岐し、第2のコード300が実行されることでトレース処理が行われる。
出力部150は、フックコードを埋め込むことで変換された変換済み第1のコード210、第2のコード300を出力する。さらに、出力部150は、フックポイントHPと関連付けられた置換コードを出力する。
このように、変換済み第1のコード210の実行において、コードの実行がフックポイントHPへ到達した際、フックコードが実行されることによって第2のコード300へと実行制御が移り、第2のコード300によるトレース処理が実行される。
第2のコード300の実行時には、出力部150により出力された置換コードが実行された上で、第1のコード200のフックポイントHPへと実行制御が移る。このため、第2のコード300の実行後には、第1のコード200がフックポイントHPから引き続き実行される。つまり、第1のコード200の実行は、第2のコード300の実行に係わらず、継続して行われる。
すなわち、コード変換装置100によれば、トレースに際してソースコードが不要であり、さらに動的変換処理を伴わずに第1のコード200のトレース処理ができる。このため、コード変換装置100によれば、フックポイントHPにフックコードを埋め込むフックコード埋め込み方式のトレース技術を用いる場合において、ソースコードに改変せずに、オーバヘッドを抑えたプログラム実行のトレースを実現することができる。
本実施形態では、各エントリポイントに挿入されるフックコードは、フックポイントHPから対応するエントリポイントへの分岐命令である。また、フックポイント特定処理は、どのエントリポイントへ分岐したかによって、呼び出し元のフックポイントHPを特定する。このため、トレース処理後に実行すべき置換コード、及び復帰すべき第1のコード200のアドレスを特定できる。
本実施形態では、置換コードが関数呼び出しであった場合、CPUの特定レジスタには、関数実行後の返りアドレスが保存される。返りアドレスは、フックポイントHPのアドレスに等しい。そこで、フックポイント特定処理では、当該特定レジスタを参照することによって、呼び出し元のフックポイントHPを特定する。このため、フックポイントHP毎にエントリポイントを用意することなく、復帰すべき第1のコード200のアドレスを特定できる。
本実施形態では、仮想アドレス空間のうち、コード領域とデータ領域との間に実行可能かつ未使用なメモリ領域がある場合、第2のコード300が当該領域に配置される。このため、第1のコード200の実行に影響を及ぼすことなく、同一プロセス空間に第1のコード200と第2のコード300とを配置できる。さらに、プログラムの実行開始前にアドレス特定部130の処理が実行されるため、プログラム開始前にコード変換部140による処理も実行できる。つまり、プログラム実行開始時の処理量を削減することができる。
本実施形態では、第2のコード300は、第1のコード200の実行終了時に呼び出されて実行される実行後処理を有する。このため、例えば、第2のコード300がトレースした結果(トレースログ)がバッファとしてメモリ上に蓄積されていた場合、第1のコード200の実行が終了して当該メモリが解放される前に、当該トレースログを二次記憶装置などに出力することができる。
なお、このような処理は、フックコードから呼び出された際に実行することは困難である。なぜなら、フックコードから呼び出された時点では、第1のコード200の実行が終了するか否か判定できないからである。また、フックコードから呼び出される度に二次記憶装置などに出力する方法も考えられるが、出力の際に発生するオーバヘッドが大きくなってしまうという問題がある。
本実施形態では、第1のコード200の中で最後に呼び出されるフックポイントHPから、第2のコード300の後処理を実行するルーチンへ分岐するフックコードが、当該フックポイントHPへ挿入される。プログラムの最後に実行されるコードは、バイナリ形式によって定まっている。例えば、ELFバイナリでは.finiセグメントが最後に実行されるため、当該セグメントの最後のフックポイントHPは、第1のコード200によって確実に最後に実行されるフックポイントHPである。このため、第2のコード300による後処理を確実に実行できる。
ここで、本実施形態に係るコード変換装置100の特徴について整理する。本実施形態に係るコード変換装置100は、ソフトウェアのトレースに関する以下の要件を満足する。
(a)コンテキスト情報を確実に取得できること
不具合の修正に利用可能となる情報の欠損を避けるため、確実にコンテキスト情報を取得できる必要がある。
(b)ソースコード無しでトレースできること
ソースコードや、再コンパイルが必要となるトレース技術は、開発者が利用する場合は有用であるが、ソフトウェアリリース後において、ユーザが利用する場合には現実的ではない。ソフトウェアによっては、実行可能バイナリのみが配布され、原理的にソースコードに頼ったトレースが不可能な場合もある。
(c)低オーバヘッドであること
トレース中であってもユーザは実際にソフトウェアを使用しているため、オーバヘッドはなるべく抑える必要がある。
ここで、このような要件に基づいて従来のトレース技術について考察する。まず、サンプリング方式は、要件(a)を満足しないため適用できない。サンプリング方式では、任意の場所をフックすることは困難であるため、必要となるコンテキスト情報を取得することはできない。
また、フック埋め込み方式のうち、ソース埋め込み型は、要件(b)を満足しないため適用できない。
要件(c)については、実際にgprofとDtraceとを例として、ターゲットプログラムの実行に伴って発生する実行時間オーバヘッドを測定した。両者ともトレースログとして、プログラム実行中に呼び出された全ての関数についてコールグラフを記録した。
表3は、gprofのオーバヘッド測定環境を示す。表4は、DTraceの測定環境を示す。表5は、ターゲットプログラムの実行条件を示す。ターゲットプログラムは、何れも同バージョンのgzip(http://www.gnu.org/software/gzip/参照)、perl(http://www.perl.org/参照)、tar(http://www.gnu.org/software/tar/参照)を同じコンパイルオプションによってコンパイルしたものを用いた。
Figure 2009237610
Figure 2009237610
Figure 2009237610
各ターゲットプログラムを定められた測定環境の下で、トレース無し及びトレースありの状態で実行し、それぞれの実行時間と各トレーサのオーバヘッドを測定した。表6及び表7は、当該測定結果を示す。
Figure 2009237610
Figure 2009237610
動作環境の違いによってターゲットプログラムの本来の実行時間が異なるため、オーバヘッドで比較する。DTraceのオーバヘッドは、CTraceとは比較にならないほど大きい。これは、関数callのフックによりフックコードの実行が発生する度にコンテキストスイッチが発生するためである。さらに、ターゲットプログラム実行中にフックポイントの検出やフックコードへの変換といった動的変換処理が行われる動的変換型の欠点である。
このようなオーバヘッドは、ソフトウェア開発者がデバッグ時に用いるのには許容範囲であったとしても、ソフトウェアのリリース後に、ユーザがトレースを実行する際には非現実的である。
一方、CTraceのように、コンテキストスイッチが発生しないタイプのトレースでは、オーバヘッドは、数%から多くても数十%に収まる。すなわち、ユーザがソフトウェアの実行をトレースするためには、コンテキストスイッチや動的変換処理が発生しないことが必須であると言える。
上述したように、従来のトレース方式は何れも、ソースコードに改変を加えずにプログラム実行を低いオーバヘッドでトレースすることはできず、ユーザが利用するソフトウェアのトレース方式として適当ではない。本実施形態に係るコード変換装置100は、上述した従来のトレース方式の問題を解決する。
なお、上述した測定では、オーバヘッドとして時間の観点から比較したが、トレースログを取得していく際のもう一つの問題は、ログのサイズである。トレースログは、正常、異常に係わらず取得されていくため、適当なタイミングでトレースログのローテーションが行われないと、ログのサイズが膨大となる。このようなログは、メモリ上のバッファ、ディスクなどのリソースを圧迫するだけではなく、不要なデータの肥大化による有用なログの埋没を招く。
このような問題について、例えば、特開2002-215431号公報では、記録するタイムスタンプの情報を減らすなどして、メモリ上のバッファ使用量を抑える技術が開示されている。また、特開2004-30505号公報では、不具合が発生した場合にのみトレースログを二次記憶装置に出力するなどして、蓄積されるログのサイズを抑える技術が開示されている。ログのサイズに関する問題については、コード変換装置100でも、これらの技術を用いて解決すればよい。
[第2実施形態]
次に、本発明の第2実施形態について説明する。本実施形態ではプロセス空間500への第2のコード300の配置方法が第1実施形態と異なる。なお、以下、上述した第1実施形態と異なる部分について主に説明し、第1実施形態と同様な部分については、その説明を適宜省略する。
(1)コード変換装置の機能
第1実施形態では、第2のコード300を静的に第1のコード200の空き領域に配置することによって、全ての処理を第1のコード200の実行開始前に静的に行うことが可能であった。しかし、第1のコード200の空き領域が、第2のコード300のサイズより大きいことが条件となる。実験の結果、第2のコード300が関数呼び出しをトレースするような処理であった場合には、当該条件が満たされることを確認した。
しかし、空き領域のサイズは実行されるプログラムに依存するとともに、第2のコード300のサイズはトレース処理の内容に依存する。このため、上述した条件を満たさない場合も起こり得る。
そこで、本実施形態では、第2のコード300は、動的リンクライブラリとして第1のコード200のプロセス空間500に配置される。動的リンクライブラリの配置先アドレスは、プログラムの実行開始時にローダによって決定される。
例えば、第1のコード200が実行される際、ローダは、第2のコード300を含める。また、ローダは、ロードすべき全ての動的リンクライブラリを参照し、動的リンクライブラリのそれぞれが重ならないように配置する。このため、第2のコード300のサイズが第1のコード200の空き領域よりも大きくなる問題は起こらない。本実施形態に係るコード変換装置100は、第2のコード300を第1のコード200の動的リンクライブラリとしてロードする。
フックポイント検出部110及び第2のコード生成部120の機能は、第1実施形態に係るコード変換装置100とほぼ同様である。
まず、ソースコードの改変をすることなく、第2のコード300を第1のコード200の動的リンクライブラリとしてプロセス空間500へ配置する方法について説明する。例えば、LinuxやFreeBSDといったUNIX(登録商標)互換OSなどで可能なLD_PRELOAD環境変数を用いる方法がある。
LD_PRELOADは、プログラムコードによって指定された動的リンクライブラリがロードされる前に、ローダによって優先的に指定したライブラリをロードする仕組みである。図8(a)及び(b)は、LD_PRELOADによるライブラリのロードを説明する説明図である。
例えば、C言語のputs関数を用いるようなプログラム(test.o)では、ローダは、プログラム実行開始時にlibcライブラリをロードする。そこで、以下にように、LD_PRELOADが自作の同名ライブラリ(./libc)をロードすることによって、puts関数を自作の関数(myputs)に置き換えることができる。
$ LD_PRELOAD=./libc ./test.o
この仕組みを利用することによって、第1のコード200の実行時に、第2のコード300を共有ライブラリとしてロードすれば、上述した問題は解決する。
しかし、動的リンクライブラリの配置先アドレスは、プログラム実行開始時にローダによって決定されるため、第2のコード300のアドレスを第1のコード200の実行開始前には特定することができない。そこで、アドレス特定部130、コード変換部140及び出力部150の処理は、ローダによる第2のコード300のロードが完了し、プロセス空間500に第2のコード300が配置された後に呼び出されることが要求される。例えば、プログラムローダ(linuxではld.so)に対して拡張実装することによって、このような要求に対応できる。
アドレス特定部130は、ローダによって配置された第2のコード300を参照することによって、第2のコード300の配置先アドレスを特定する。具体的には、アドレス特定部130は、第1のコード200と対応する仮想アドレス空間のうち、共有ライブラリとして第2のコード300を配置可能なアドレス(配置可能アドレス)を特定する。
なお、第2のコード生成部120は、アドレス特定部130によって特定された配置可能アドレスをアドレス情報として前記第2のコードに含める。
コード変換部140は、既にメモリ上にロードされている第1のコード200に対してフックコードを埋め込む。第1のコード200の配置先アドレスは、フックポイント検出部110が解析した時点から変化していないため、フックポイント検出情報400のアドレスを参照することによってフックポイントHPの特定は容易である。
ただし、フックポイントHPは、コード領域(図5及び図6に示すLOAD1)に存在するため、書き換えは許可されていない。そこで、内容を書き換える際には、一時的に当該アドレスの権限を変更する必要がある。例えば、linuxでは、mprotect()システムコールを利用する。
出力部150は、ローダの通常処理に制御を渡すだけである。ローダは、第2のコード300以外の動的リンクライブラリを全てロードし、変換済み第1のコード210の実行を開始する。変換済み第1のコード210が実行された際における第2のコード300の処理については、第1実施形態と同様であるため省略する。
以上説明したように、本実施形態では、第2のコード300に対するサイズ制限が生じない。さらに、本実施形態では、メモリにロードされたコードに対して、ロードの都度コード変換部140による処理が行われるため、第1のコード200を実行する度に、変換対象とするフックポイントHPを柔軟に変更することもできる。
例えば、関数呼び出しをトレースするような場合において、(i)全ての関数をトレースする場合、(ii)共有ライブラリ上の関数のみトレースする場合、(iii)ローカル関数のみをトレースする場合など、プログラムの実行毎にトレースの対象を切り替えることができる。
第1のコード200上の不具合のみを調べる場合には、共有ライブラリ関数の呼び出しまでトレースすることは無意味であるため、ローカル関数のみをトレースすればよい。また、第1のコード200がシステム上のどのようなリソースを参照しているか調べる場合には、共有ライブラリ関数のみをトレースすればよい。
このように、トレースする目的に応じて、フックコードを挿入するフックポイントHPを柔軟に切り替える方法についてさらに説明する。上述したトレースを例にすると、フックポイント検出部110がフックポイントHPを検出する際、それぞれのフックポイントHPにローカル関数呼び出しであるか、動的リンクライブラリ関数呼び出しであるかを区別するフラグを設定する。ライブラリ関数の呼び出しである場合には、必ずpltセクション経由での呼び出しが発生するため、上述した関数の判別は容易である。
コード変換部140は、コードの実行時において、どの関数を実行するかを規定するコード変換規則700(図3参照)を入力とし、フックポイント検出情報400に含まれるフックポイントHPのうち、コード変換規則700に合致するフックポイントHPにのみ、フックコードを挿入していけばよい。
すなわち、コード変換部140は、フックポイント検出部110によって検出されたフックポイントHPのうち、フックコードを挿入するためのコード変換規則700が特定のフックポイントHPにのみ与えられた場合、コード変換規則700によって指定されたフックポイントHPにのみ、フックコードを埋め込む。
(2)作用・効果
本実施形態では、第1のコード200の実行開始時にローダによって共有ライブラリとのリンク処理が実行される場合、当該処理に割り込むことによって、第2のコード300が共有ライブラリとして第1のコード200にリンクされる。このため、第1のコード200の実行に影響を及ぼすことなく、また、第2のコード300のサイズに係わらず、同一のプロセス空間(プロセス空間500)に第1のコード200と第2のコード300とを配置できる。
本実施形態では、例えば、第1のコード200を実行する状況によってトレースすべきフックポイントHPが異なるような場合、与えられたコード変換規則700がトレースすべきフックポイントHPを特定する。また、コード変換部140は、選択的にフックポイントHPのコード変換を行うことによって、フックコードを挿入する。このため、必要な部分のみのトレース処理を実行できる。
[第3実施形態]
次に、本発明の第3実施形態について説明する。本実施形態では、第2実施形態と同様に、第1のコード200の動的リンクライブラリとして、第2のコード300がプロセス空間500へ配置する。ただし、第2実施形態とは異なり、コード変換装置100の全ての動作は、第1のコード200の実行開始前に行われる。このような動作によれば、第2実施形態と異なり、第1のコード200の実行開始時にコード変換装置100の処理によるオーバヘッドが発生することを回避できる。
(1)コード変換装置の機能
第2実施形態でも記載したとおり、通常、動的リンクライブラリの配置アドレスは、プログラム実行開始時に、ロードされる動的リンクライブラリを参照することによってローダが解決する。このため、実行開始前に当該アドレスを特定することはできない。
そこで、アドレス特定部130は、第2のコード300をあらかじめ参照することによって、配置可能なアドレスを特定する。このような仕組みは既に実現されており、linuxやFreeBSDなどのUNIX(登録商標)互換OSではprelink(prelink, http://people.redhat.com/jakub/prelink.pdf参照)と呼ばれる。prelinkは、元々、ローダによるプログラム実行開始時のアドレス解決処理を事前に行うことによって、プログラムの処理開始までの時間を短縮するための技術である。
具体的には、アドレス特定部130は、prelinkする各ライブラリを参照し、配置アドレスを決定する。さらに、アドレス特定部130は、決定した配置アドレスを各ライブラリのプログラムヘッダにあらかじめ書き込む。実際にプログラムが起動される場合、各ライブラリは、プログラムヘッダにより指定されたアドレスに配置されていく。
図9(a)及び(b)は、試作した動的リンクライブラリに対するprelink実行前後のプログラムヘッダを示す。prelink後は、配置先のアドレスが固定されている(図9(b)の園内参照)。
すなわち、アドレス特定部130は、第1のコード200の実行開始時に、ローダによる共有ライブラリのロード処理が実行される場合、ロード処理の開始前に当該ロード処理をフックし、第2のコード300を共有ライブラリとしてプロセス空間500上に配置する。
また、出力部150は、第1のコード200の実行開始時に、第2のコード300に含まれるアドレス情報を共有ライブラリのロード処理に提供することによって、第2のコード300が共有ライブラリとしてプロセス空間500上に配置される。
(2)作用・効果
本実施形態では、第1のコード200の実行開始前に、第2のコード300を共有ライブラリとして配置可能なアドレスが、事前に解決(プレリンク)され、コードの実行時には、当該アドレスへ第2のコード300が配置される。
このため、第1のコード200の実行に影響を及ぼすことなく、また、第2のコード300のサイズに係わらず、同一のプロセス空間(プロセス空間500)に第1のコード200と第2のコード300とを配置できる。さらに、プログラムの実行開始前にアドレス特定部130の処理が実行されるため、プログラム開始前にコード変換部140による処理も実行できる。つまり、プログラム実行開始時の処理量を削減することができる。
[その他の実施形態]
上述したように、本発明の第1実施形態〜第3実施形態を通じて本発明の内容を開示したが、この開示の一部をなす論述及び図面は、本発明を限定するものであると理解すべきではない。この開示から当業者には様々な代替実施の形態が明らかとなろう。
例えば、上述した第1実施形態では、第2のコード300は、第1のコード200の実行終了時に呼び出されて実行される実行後処理を有していたが、第2のコード300は、実行後処理を有していなくても構わない。
また、上述した第1実施形態では、仮想アドレス空間のうち、コード領域とデータ領域との間に実行可能かつ未使用なメモリ領域がある場合、第2のコード300が当該領域に配置されたが、第2のコード300は、必ずしも当該領域に配置されなくてもよい。
このように、本発明は、ここでは記載していない様々な実施の形態などを含むことは勿論である。したがって、本発明の技術的範囲は、上述の説明から妥当な特許請求の範囲に係る発明特定事項によってのみ定められるものである。
プログラムトレースの原理を説明する説明図である。 メモリダンプとコンテキスト情報との関係を示す図である。 本発明の実施形態に係るコード変換装置100の全体概略構成図である。 本発明の実施形態において用いられるコードの概略構成を示す図である。 本発明の第1実施形態に係る第1のコード200がELFバイナリである場合におけるプログラムヘッダの例を示す図である。 本発明の第1実施形態に係る第2のコード300が配置可能な領域を示す図である。 本発明の第1実施形態に係るコード変換装置100を構成する各ブロックの動作フローを示す図である。 本発明の第2実施形態に係るLD_PRELOADによるライブラリのロードを説明する説明図である。 本発明の第3実施形態に係る動的リンクライブラリに対するprelink実行前後のプログラムヘッダを示す図である。
符号の説明
100…コード変換装置、110…フックポイント検出部、120…第2のコード生成部、130…アドレス特定部、140…コード変換部、150…出力部、200…第1のコード、210…変換済み第1のコード、300…第2のコード、400…フックポイント検出情報、500…プロセス空間、600…フックポイント検出規則、700…コード変換規則、HP…フックポイント

Claims (10)

  1. 入力された第1のコードのプロセス空間上に第2のコードを配置するために、前記第1のコードを変換するコード変換装置であって、
    あらかじめ与えられた規則に従い、前記第1のコードから前記第2のコードを呼び出すポイントをフックポイントに設定するとともに、前記フックポイント上のコードを置換コードとした場合において、前記第1のコードの中から前記フックポイントを検出し、前記フックポイントのアドレス及び前記置換コードをフックポイント検出情報として出力するフックポイント検出部と、
    前記第2のコードを生成する第2のコード生成部と、
    前記第2のコード生成部によって生成された前記第2のコードが配置される前記プロセス空間上のアドレスを特定するアドレス特定部と、
    前記フックポイント検出情報によって特定される前記フックポイントから、前記アドレス特定部によって前記アドレスが特定されたコードを前記第2のコードへ分岐するために用いられるフックコードとした場合において、前記置換コードを前記フックコードに置き換えるコード変換部と、
    前記コード変換部によって変換された変換済み第1のコード、前記第2のコード及び前記フックポイント検出情報を出力する出力部と
    を備え、
    前記第2のコード生成部によって生成される前記第2のコードは、
    前記第1のコードから前記第2のコードを呼び出す前記フックポイントを特定するフックポイント特定処理と、
    前記フックポイント検出情報を参照し、前記フックポイントに対応する前記置換コードを実行する置換コード実行処理と、
    コードの実行制御を前記フックポイントへ復帰させる復帰処理と
    を含むコード変換装置。
  2. 前記フックポイントは、複数設定されており、
    前記第2のコード生成部は、前記第2のコード上に、それぞれの前記フックポイントに対応するエントリポイントを用意し、
    前記フックコードは、前記エントリポイントへの分岐命令であり、
    前記フックポイント特定処理は、前記エントリポイントに基づいて前記フックポイントを特定する請求項1に記載のコード変換装置。
  3. 前記フックポイント特定処理は、前記置換コードが関数を呼び出す分岐命令であった場合、前記関数の呼び出しに対する返りアドレスを参照することによって前記フックポイントを特定する請求項1に記載のコード変換装置。
  4. 前記アドレス特定部は、前記第1のコードのコード領域と、前記第1のコードのデータ領域との間に未使用のメモリ領域が存在し、かつ前記メモリ領域のサイズが前記第2のコードのサイズより大きい場合、前記メモリ領域に前記第2のコードを配置する請求項1に記載のコード変換装置。
  5. 前記アドレス特定部は、前記第1のコードの実行開始時にローダによる共有ライブラリのロード処理が実行される場合、前記ロード処理の開始前に前記ロード処理をフックし、前記第2のコードを前記共有ライブラリとして前記プロセス空間上に配置する請求項1に記載のコード変換装置。
  6. 前記アドレス特定部は、前記第1のコードと対応する仮想アドレス空間のうち、共有ライブラリとして前記第2のコードを配置可能な配置可能アドレスを特定し、
    前記第2のコード生成部は、前記配置可能アドレスをアドレス情報として前記第2のコードに含め、
    前記出力部は、前記第1のコードの実行開始時に、前記アドレス情報を前記共有ライブラリのロード処理に提供することによって、前記第2のコードを前記共有ライブラリとして前記プロセス空間上に配置する請求項1に記載のコード変換装置。
  7. 前記コード変換部は、前記フックポイント検出部によって検出された前記フックポイントのうち、前記フックコードを挿入するためのコード変換規則が特定のフックポイントにのみ与えられた場合、前記コード変換規則によって指定された前記フックポイントにのみ、前記フックコードを埋め込む請求項5に記載のコード変換装置。
  8. 前記第2のコード生成部が生成する前記第2のコードは、前記フックポイント特定処理、前記置換コード実行処理、及び前記復帰処理に加え、前記第1のコードの実行終了時に呼び出されて実行される実行後処理を含む請求項1に記載のコード変換装置。
  9. 前記フックポイント検出部は、前記第1のコードの中から最後に実行される前記フックポイントを検出し、
    前記コード変換部は、最後に実行される前記フックポイントに、前記第2のコードの前記実行後処理を呼び出す前記フックコードを挿入する請求項8に記載のコード変換装置。
  10. 入力された第1のコードのプロセス空間上に第2のコードを配置するために、前記第1のコードを変換するコード変換方法であって、
    あらかじめ与えられた規則に従い、前記第1のコードから前記第2のコードを呼び出すポイントをフックポイントに設定するとともに、前記フックポイント上のコードを置換コードとした場合において、前記第1のコードの中から前記フックポイントを検出し、前記フックポイントのアドレス及び前記置換コードをフックポイント検出情報として出力するステップと、
    前記第2のコードを生成するステップと、
    生成された前記第2のコードが配置される前記プロセス空間上のアドレスを特定するステップと、
    前記フックポイント検出情報によって特定される前記フックポイントから、前記アドレスが特定されたコードを前記第2のコードへ分岐するために用いられるフックコードとした場合において、前記置換コードを前記フックコードに置き換えるステップと、
    前記置き換えるステップにおいて変換された変換済み第1のコード、前記第2のコード及び前記フックポイント検出情報を出力するステップと
    を備え、
    前記生成するステップにおいて生成される前記第2のコードは、
    前記第1のコードから前記第2のコードを呼び出す前記フックポイントを特定し、
    前記フックポイント検出情報を参照し、前記フックポイントに対応する前記置換コードを実行し、
    コードの実行制御を前記フックポイントへ復帰させる
    コード変換方法。
JP2008079220A 2008-03-25 2008-03-25 コード変換装置及びコード変換方法 Pending JP2009237610A (ja)

Priority Applications (1)

Application Number Priority Date Filing Date Title
JP2008079220A JP2009237610A (ja) 2008-03-25 2008-03-25 コード変換装置及びコード変換方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
JP2008079220A JP2009237610A (ja) 2008-03-25 2008-03-25 コード変換装置及びコード変換方法

Publications (1)

Publication Number Publication Date
JP2009237610A true JP2009237610A (ja) 2009-10-15

Family

ID=41251528

Family Applications (1)

Application Number Title Priority Date Filing Date
JP2008079220A Pending JP2009237610A (ja) 2008-03-25 2008-03-25 コード変換装置及びコード変換方法

Country Status (1)

Country Link
JP (1) JP2009237610A (ja)

Cited By (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
KR20120063496A (ko) * 2009-09-02 2012-06-15 어드밴스드 마이크로 디바이시즈, 인코포레이티드 경량 서비스 기반의 동적 바이너리 재작성기 프레임워크
JP2012164098A (ja) * 2011-02-06 2012-08-30 Mitsubishi Electric Corp エントリ書換装置及びエントリ書換プログラム
WO2012124841A1 (ko) * 2011-03-15 2012-09-20 현대자동차 주식회사 통신 테스트 장치 및 방법
WO2012131933A1 (ja) * 2011-03-30 2012-10-04 富士通株式会社 情報処理装置、プログラム、および解析方法
JP2013186731A (ja) * 2012-03-08 2013-09-19 Mitsubishi Electric Corp コンピュータシステムおよびコンピュータシステムを用いたネットワークシステム
JP2017505944A (ja) * 2013-12-30 2017-02-23 ノキア テクノロジーズ オーユー マルウェア検出検査方法及び装置

Cited By (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
KR20120063496A (ko) * 2009-09-02 2012-06-15 어드밴스드 마이크로 디바이시즈, 인코포레이티드 경량 서비스 기반의 동적 바이너리 재작성기 프레임워크
KR101697719B1 (ko) 2009-09-02 2017-01-18 어드밴스드 마이크로 디바이시즈, 인코포레이티드 경량 서비스 기반의 동적 바이너리 재작성기 프레임워크
JP2012164098A (ja) * 2011-02-06 2012-08-30 Mitsubishi Electric Corp エントリ書換装置及びエントリ書換プログラム
WO2012124841A1 (ko) * 2011-03-15 2012-09-20 현대자동차 주식회사 통신 테스트 장치 및 방법
US9009532B2 (en) 2011-03-15 2015-04-14 Hyundai Motor Company Communication test apparatus and method
WO2012131933A1 (ja) * 2011-03-30 2012-10-04 富士通株式会社 情報処理装置、プログラム、および解析方法
JPWO2012131933A1 (ja) * 2011-03-30 2014-07-24 富士通株式会社 情報処理装置、プログラム、および解析方法
JP2013186731A (ja) * 2012-03-08 2013-09-19 Mitsubishi Electric Corp コンピュータシステムおよびコンピュータシステムを用いたネットワークシステム
JP2017505944A (ja) * 2013-12-30 2017-02-23 ノキア テクノロジーズ オーユー マルウェア検出検査方法及び装置
US10181033B2 (en) 2013-12-30 2019-01-15 Nokia Technologies Oy Method and apparatus for malware detection

Similar Documents

Publication Publication Date Title
US7661094B2 (en) Real-time software diagnostic tracing
US9274923B2 (en) System and method for stack crawl testing and caching
US6634020B1 (en) Uninitialized memory watch
US7761855B2 (en) Computer program product and system for altering execution flow of a computer program
US5987250A (en) Transparent instrumentation for computer program behavior analysis
US8266608B2 (en) Post-compile instrumentation of object code for generating execution trace data
US8739135B2 (en) Static instrumentation macros for fast declaration free dynamic probes
US7900198B2 (en) Method and system for parameter profile compiling
US8887141B2 (en) Automatically modifying a native code module accessed from virtual machine bytecode to determine execution information
JP2000181725A (ja) 実行可能なコ―ドを改変し、追加機能を付与するための方法およびシステム
US20120167057A1 (en) Dynamic instrumentation of software code
US20090172653A1 (en) Compiling and Inserting Code Snippets At Runtime
US20110126179A1 (en) Method and System for Dynamic Patching Software Using Source Code
US20110029819A1 (en) System and method for providing program tracking information
US20090320007A1 (en) Local metadata for external components
JP2009237610A (ja) コード変換装置及びコード変換方法
US8533683B2 (en) Stack walking enhancements using sensorpoints
US20100275185A1 (en) System and Method for High Performance Coverage Analysis
Villazón et al. Advanced runtime adaptation for Java
US20080127119A1 (en) Method and system for dynamic debugging of software
US20080127118A1 (en) Method and system for dynamic patching of software
US7409677B1 (en) Method and system for creation and use of embedded trace description
EP3635561B1 (en) Asynchronous operation query
Hammacher Design and implementation of an efficient dynamic slicer for Java
JP2005338987A (ja) 例外テスト支援プログラム及び例外テスト支援装置