2

fopen、fread などの glibc の関数をフックしようとしていますが、フック関数では、glibc と同じ関数を使用する必要があります。このような:

// this is my fopen
FILE *fopen(.....)
{
    fopen(....);// this is glibc fopen
}

dlsym を使用してこれを行う 1 つの方法を見つけましたが、この方法では、すべての glibc 関数呼び出しを、dlsym を使用して glibc 関数を呼び出す内部のラッパーに置き換える必要があります。ラッパー関数をコーディングせずに同じ仕事をする別の方法がどこにあるか知りたいです。私はこれを試したことがあります:

fopen.c

....fopen(..)
{
  myfopen(..);
}

myfopen.c

myfopen(..)
{
  fopen(...);// glibc version
}

main.c

int main()
{
  fopen(...);
}

$ gcc -c *.c
$ gcc -shared -o libmyopen.so myopen.o
$ gcc -o test main.o fopen.o libmyopen.so

私の理解では、gcc はコマンド ラインで指定されているように左から右にリンクするため、main.o は fopen.o で fopen を使用し、fopen.o は libmyfopen.so で myfopen を使用し、libmyfopen.so は glibc で fopen を使用します。しかし、実行中にセグメント障害が発生しました.gdbは、fopenとmyfopenの再帰呼び出しがあることを示しています. 私は少し混乱しています。誰でも理由を説明できますか?

4

1 に答える 1

3

私の理解では、gccはコマンドラインで指定されたように左から右にリンクするため、main.oはfopen.oでfopenを使用し、fopen.oはlibmyfopen.soでmyfopenを使用し、libmyfopen.soはglibcでfopenを使用します

あなたの理解は間違っています。myfopenfromlibmyfopen.soは、利用可能な最初の定義をfopen使用します。セットアップでは、その定義はプログラムにfopen.oリンクされているtestため、無限再帰が発生し、スタックの枯渇によるクラッシュが発生します。

これを確認するgdb ./testには、 を実行し、クラッシュするまで実行し、 を使用しbacktraceます。fopenとの呼び出しが無限に続くことがわかりmyfopenます。

シンボル fopen は、コンパイル時に libc のシンボルに結合されません

正しい:ELFライブラリは、シンボル (fopenこの場合) を定義する必要があることを形式で記録しますが、他のどのモジュールがそのシンボルを定義しているかを「記憶」または気にしません。

を実行すると、これを確認できますreadelf -Wr libmyfopen.so | grep fopen

Windows DLL とは異なります。

はい。

于 2012-05-15T05:25:18.137 に答える