45

明確にするために、私の質問は、呼び出し元と呼び出し先がGCCコンパイラとリンカーを使用して同じコンパイルユニットで定義されている場合に、ある関数/シンボルから別の関数/シンボルへの呼び出しをラップ/インターセプトすることを指します。

次のような状況があります。

/* foo.c */
void foo(void)
{
  /* ... some stuff */
  bar();
}

void bar(void)
{
  /* ... some other stuff */
}

これらの関数への呼び出しをラップしたいと思いますが、ld のオプションを使用して (ある程度まで) それを行うことができます--wrap(そして、ld のオプションの結果によって期待されるように __real_foo と __real_bar を呼び出す __wrap_foo と __wrap_bar を実装し--wrapます)。

gcc -Wl,--wrap=foo -Wl,--wrap=bar ...

私が抱えている問題は、これがこのコンパイル単位の外部からの foo と bar への参照に対してのみ有効になる (そしてリンク時に解決される) ことです。つまり、foo.c 内の他の関数からの foo および bar への呼び出しはラップされません。

コンパイル単位内からの呼び出しは、リンカーのラッピングの前に解決されます

objcopy --redefine-symを使用してみましたが、シンボルとその参照の名前が変更されるだけです。

and (foo.o 内) の呼び出しをfooand (リンカーのオプションによって他のオブジェクト ファイルで解決されるのと同じように) に置き換えたいと思います。*.o ファイルをリンカーのオプションに渡す前に、foo を変更する必要はありません。 .c のソース コード。bar__wrap_foo__wrap_bar--wrap--wrap

そうすれば、foo.o の外で行われる呼び出しだけでなく、 とfooへのすべての呼び出しに対してラッピング/インターセプトが行われます。bar

これは可能ですか?

4

7 に答える 7

8
#include <stdio.h>
#include <stdlib.h>

//gcc -ggdb -o test test.c -Wl,-wrap,malloc
void* __real_malloc(size_t bytes);

int main()
{
   int *p = NULL;
   int i = 0;

   p = malloc(100*sizeof(int));

   for (i=0; i < 100; i++)
       p[i] = i;

   free(p);
   return 0;
}

void* __wrap_malloc(size_t bytes)
{
      return __real_malloc(bytes);
}

そして、このコードをコンパイルしてデバッグするだけです。reall malloc を呼び出すと、呼び出された関数は __wrap_malloc を呼び出し、__real_malloc は malloc を呼び出します。

これが通話を傍受する方法だと思います。

基本的には、ld が提供する --wrap オプションです。

于 2015-02-27T22:23:07.163 に答える
6

これは文書化されているように機能しているようです:

 --wrap=symbol
       Use a wrapper function for symbol. 
       Any undefined reference to symbol will be resolved to "__wrap_symbol". ...

上記の未定義に注意してください。リンカが を処理するとき、foo.oは未定義でbar()ないため、リンカはそれをラップしません。なぜそのようにしたのかはわかりませんが、おそらくこれが必要なユースケースがあるでしょう。

于 2012-12-23T15:43:44.370 に答える
4

--undefinedで使用すると、目的を達成できます--wrap

  -u SYMBOL, --undefined SYMBOL
                              Start with undefined reference to SYMBOL
于 2013-11-18T02:43:03.380 に答える