2011-10-18 2 views
5

私はmalloc/free/calloc/reallocなどをいくつかのインターポーザーにLD_PRELOADで挿入しようとしています。小さなテストでは、freeが検出されていても、mallocだけが挿入されているようです(出力を参照)。LD_PRELOADはmallocでのみ動作し、フリーではありません

出力に「NANO:free(x)」という行が含まれていると思われますが、この行はありません。

考える

// compile with: gcc test.cc 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char* argv[]) { 

    void* p = malloc(123); 
    printf("HOST p=%p\n", p); 
    free(p); 
} 

そして

// compile with: g++ -O2 -Wall -fPIC -ldl -o libnano.so -shared main.cc 
#include <stdio.h> 
#include <dlfcn.h> 

typedef void *(*MallocFunc)(size_t size); 
typedef void (*FreeFunc)(void*); 

// Original functions 
static MallocFunc real_malloc = NULL; 
static FreeFunc real_free = NULL; 

static void __nano_init(void) { 
    // Override original functions 
    real_malloc = (MallocFunc)dlsym(RTLD_NEXT, "malloc"); 
    if (NULL == real_malloc) { 
     fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); 
    } else { 
     fprintf(stderr, "NANO: malloc() replaced @%p\n", real_malloc); 
    } 

    real_free = (FreeFunc)dlsym(RTLD_NEXT, "free"); 
    if (NULL == real_free) { 
     fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); 
    } else { 
     fprintf(stderr, "NANO: free() replaced @%p\n", real_free); 
    } 
} 

// replacement functions 
void *malloc(size_t size) { 
    if(real_malloc==NULL) __nano_init(); 

    void *p = NULL; 
    fprintf(stderr, "NANO: malloc(%lu) = ", size); 
    p = real_malloc(size); 
    fprintf(stderr, "%p\n", p); 

    return p; 
} 

void free(void* ptr) { 
    if(real_free==NULL) __nano_init(); 

    fprintf(stderr, "NANO: free(%p)\n", ptr); 
    real_free(ptr); 

    return; 
} 

実際の出力は次のようになります。

% ./a.out 
NANO: malloc() replaced @0x3b36274dc0 
NANO: free() replaced @0x3b36272870 
NANO: malloc(123) = 0x601010 
HOST p=0x601010 

答えて

9

あなたがC++をコンパイルしています。つまり、(デフォルトでは)関数はC++のABIに合うように名前が変更されています。残念ながら、フックしようとしている関数はではなく、という名前のmangledなので、間違った(存在しない)関数をフックすることになります。

修正方法は、a)extern "C" { }ブロック内にラッパーを定義するか、またはa)関数のヘッダーを含めるようにしてください(#include <cstdlib>など)。これにより、mallocfreeの宣言がextern "C"ラッパーに引き込まれ、コンパイラに名前をつけないように指示します。

理由malloc作品はmallocなくfreeの宣言ではおそらく<stdio.h>または<dlfcn.h>引っ張ります。したがって、mallocはアンマングル化されていますが、freeはマングリングされています。

注意:glibcを使用している場合は、malloc hooksを使用してメモリ割り当て機能をフックする必要があります。 glibcは、あなたのフックに干渉するかもしれないシンボルのバージョン管理を使って、かなり奇妙なことをします。使用方法の例はリンク先のドキュメントにあります.C++を使用している場合はextern "C"を忘れないでください!

+0

名前のマングリング。見つけたこれは、私が使用しているすべての例がC/gccのどこにあるかを示しています。私はg ++に行ったときに気づいたはずです。 チップをありがとう - 今のところ私は直線LD_PRELOADテクニックを評価したいと思います。私はmallocフックの利点を確信していません。 – Justicle

+0

@bdonianあなたがゲームをしているなら、私はここでフォローアップの質問があります:http://stackoverflow.com/questions/7910666/problems-with-ld-preload-and-calloc-interposition-for-certain-executables – Justicle

関連する問題