web-dev-qa-db-ja.com

Linuxでsyscall関数を再実装(またはラップ)するにはどうすればよいですか?

Open()システムコールを完全に引き継いで、実際のsyscallをラップして、ロギングを実行したいとします。 これを行う1つの方法は、LD_PRELOADを使用することです open()エントリポイントを引き継ぐ(ユーザー作成の)共有オブジェクトライブラリをロードします。

次に、ユーザーが作成したopen()ルーチンは、それをopen()して呼び出し、glibc関数dlsym()へのポインターを取得します。

ただし、上記で提案したソリューションは動的ソリューションです。自分のopen()ラッパーを静的にリンクしたいとします。どうすればいいですか?メカニズムは同じだと思いますが、ユーザー定義のopen()とlibcopen()の間にシンボルの衝突があると思います。

同じ目標を達成するために他のテクニックを共有してください。

31
Stefano Borini

ldが提供するラップ機能を使用できます。 man ldから:

--wrap symbolシンボルのラッパー関数を使用します。 symbolへの未定義の参照は、__wrap_symbolに解決されます。

__real_symbolへの未定義の参照は、symbolに解決されます。

したがって、ラッパー関数にはプレフィックス__wrap_を使用し、実際の関数を呼び出す場合は__real_を使用する必要があります。簡単な例は次のとおりです。

malloc_wrapper.c

#include <stdio.h>
void *__real_malloc (size_t);

/* This function wraps the real malloc */
void * __wrap_malloc (size_t size)
{
    void *lptr = __real_malloc(size);
    printf("Malloc: %lu bytes @%p\n", size, lptr);
    return lptr;
}

テストアプリケーションtestapp.c

#include <stdio.h>
#include <stdlib.h>
int main()
{
    free(malloc(1024)); // malloc will resolve to __wrap_malloc
    return 0;
}

次に、アプリケーションをコンパイルします。

gcc -c malloc_wrapper.c
gcc -c testapp.c
gcc -Wl,-wrap,malloc testapp.o malloc_wrapper.o -o testapp

結果のアプリケーションの出力は次のようになります。

$ ./testapp
Malloc: 1024 bytes @0x20d8010
60

シンボルは、コマンドラインにリストした順序でリンカーによって解決されるため、標準ライブラリの前にライブラリをリストした場合は、信頼性が高くなります。 gccの場合、指定する必要があります

gcc <BLAH> -nodefaultlibs <BLAH BLAH> -lYOUR_LIB <OTHER_LIBS>

このようにして、ライブラリが最初に検索されて見つかります。

2
Paul Rubel