2007年06月13日

オープンソースを楽しむエンジニア達のこだわり 〜 ftrace で引数を表示する

はてなブックマークに登録

先日、 プログラムの動作をトレースするツールとして ftrace を公開しました。 その後 KLab では引き続き機能拡張を行っており、関数に渡された引数を表示 するような改良を行いました。引数が解ると自作した関数の意図しない動作を 追うときにとても便利そうです。

以下からダウンロードしておためしください

ftrace-0.92.tar.gz

注意点

  • x86(32bit) な環境でしか動作しません
  • デバッグ対象のプログラムは -g と -finstrument-functions フラグを付けてコンパイルされている必要があります。
  • 依存するライブラリは glib1.2, libelf, libdwarf です
  • debian sarge の方は
    $ apt-get install libglib1.2-dev libelfg0-dev libdwarf-dev
    
    を実行すると ./configure が通るようになります。sarge で無い方は libdwarf-dev パッケージがありませんので以下の場所から libdwarf をダウ ンロードしてインストールしてください

    David A's DWARF Page

主な実装方針は、

  • 1) 実行バイナリから引数の型情報を得る
  • 2) スタックフレームから引数情報を得て表示する

(1)にある引数の型情報を得る方法の前に、まずは(2)のスタックフレームから 引数情報を得る方法について紹介したいと思います。

まず、以下のように引数を2つ受け取る関数 func() が定義されているとします

void func(int a, int b)
{
}
int main(int argc, char *argv[])
{
    func(1, 2);
}

この関数 func() を前回紹介した __cyg_profile_func_enter() 関数で hook した際に関数 func() の引数を得るにはどうしたらよいかを考えてみたところ gcc に は __builtin_frame_address() というスタックフレームアドレスを得るビル トイン関数が用意されていることが判ったのでこれを使ってみることにしまし た。

__cyg_profile_func_enter() を以下のように定義すると

void __cyg_profile_func_enter( void *this, void *callsite )
{
    if(this == func){
        void *frame = __builtin_frame_address(1) + 8;
        printf("a=%d\n", *(int*)frame);
        frame += 4; // 変数 a は int なので 4byte 次へ
        printf("b=%d\n", *(int*)frame);
    }
}
実行結果
a=1
b=2

というように __cyg_profile_func_enter() の中から関数 func の引数を得る ことが出来ました。 この様に関数の引数が int 型であることと引数の数が判っているば正しく表 示することは出来ましたが、引数の数や型が判らないとスタックフレームの中 から正しく引数情報を得ることは出来ません。

そこで(1)に書いたように、実行バイナリから引数の数や型情報を含めた関数 のプロトタイプ情報が必要になるのですが、この方法については次回紹介させ て頂きたいと思います。
klab_gijutsu2 at 15:24│Comments(0)TrackBack(0)

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント