2009-06-15 5 views
8

私は現在、いくつかのシステムコールと低レベル関数、例えばmmapbrksbrkの使用状況を追跡する必要があるプロジェクトに取り組んでいます。これまでは関数の介在を使用していました。置き換えようとしている関数(例:mmap)と同じ名前のラッパー関数を作成し、LD_PRELOAD環境変数を設定してプログラムにロードします。私はdlsymでロードするポインタを通して実際の関数を呼び出します。dlsymを使用しないLinuxでの関数の介入

残念ながら、私がラップする機能の1つであるsbrkは内部でdlsymで使用されているため、シンボルをロードしようとするとプログラムがクラッシュします。 sbrkはLinuxのシステムコールではないので、単にsyscallを使って間接的に呼び出すことはできません。

だから、どのように私はdlsymを使用せずに、同じ名前のラッパー関数からライブラリ関数を呼び出すことができている私の質問?元の関数を参照できるコンパイラトリック(gccを使用)がありますか?

答えて

14

ldのオプション--wrap symbolを参照してください。マニュアルページから:

- wrap symbolシンボルにラッパー関数を使用します。定義されていないシンボルへの参照 は、 から "__wrap_symbol"に解決されます。未定義の が「__real_symbol」を参照すると、 はシンボルに解決されます。

これは、システム機能のため ラッパーを提供するために使用することができます。 ラッパー関数は、 "__wrap_symbol"と呼びます。 にシステム機能を呼び出す場合は、 "__real_symbol"を呼び出す必要があります。ここで

は簡単な例です:

void * 
__wrap_malloc (size_t c) 
{ 
    printf ("malloc called with %zu\n", c); 
    return __real_malloc (c); 
} 

あなたが--wrap malloc関数を使用して、この ファイルを他のコードをリンクする場合は、すべての 呼び出しは "malloc" は「 関数を呼び出しますし__wrap_malloc "と入力してください。
"__wrap_malloc"で "__real_malloc"を呼び出すと、実際には "malloc"関数が呼び出されます。

あなたは成功しますので --wrapオプション せずにリンクするだけでなく 「__real_malloc」機能を提供することを望むかもしれません。あなたがこれを行う場合は、あなた は 「__wrap_malloc」と同じファイルに 「__real_malloc」の定義を置くべきではありません。その場合、 アセンブラが より前に呼び出しを解決し、リンカが "malloc"にラップする可能性があります。

他のオプションは、それが多かれ少なかれあり、同じことの:-Pを行い、おそらくltraceのためのソースを見ることです。

ここにアイデアがあります。LD_PRELOADライブラリでコードを指すようにPLTエントリを変更することができます。これは技術的にはsbrk()の機能がコードから呼び出せます。これらのツールは、関数が呼び出されたときにモニタプログラムがあなたを通知することができ

  • GDB
  • ltraceの
  • SystemTapの

+0

これは素晴らしいです。私は--wrapオプションについて聞いたことはありませんでしたが、これは私が必要とするものです。ありがとうございました。 –

+0

明確にするために、実行ファイルをリンクするとき、またはラッパーを含むLD_PRELOADライブラリをリンクするときに、-wrapフラグを渡す必要がありますか?また、実行可能ファイルのPLTエントリの変更に関する詳細情報を提供することを検討しますか? –

+0

設計されたユースケースは* target *アプリを--wrapとリンクするためのものです。 LD_PRELOADのケースでも動作させることは可能かもしれませんが、わかりませんが、テストする必要があります。 –

2

次のようなツールを使用して控えめに関数呼び出しを調べることができます引数を調べることができます。

主な相違点は以下のとおりです。

  • gdbが使用するのは簡単
  • インタラクティブな、しかし強力なltraceのですが、あなただけの
  • のSystemTapはインタラクティブではありませんが、それは非常にすることができ、関数名を印刷することができます速く、強力です。
0

glibcを使用してホストシステムを実行している場合、libcには以前使用したランタイムダイナミックリンカの内部バックエンドがあります。私が正しく思い出すと、それは「__libc_dlsym」と呼ばれると思います。 (チェックするには、 "$ readelf -s /usr/lib/libc.a | grep dlsym"が役に立ちます。)dlsymと同じ引数と戻り値を持つ外部リンク関数として宣言し、それを使ってdlsym自体をラップします。

0

trussはお使いのシステムでは機能しませんか?これはSolaris上でのこの種のものに対しては完全に機能します。

+0

これは、Linuxでは 'strace'とまったく同じように思えます。これは、作成されたコールのリストを取得するだけでよい場合は正常に機能します。このプロジェクトでは、ラッパーにいくつかの機能を追加する必要がありました。そのためには、介入が唯一の方法だと思います。 –

関連する問題