2011-10-18 11 views
5

Próbuję interferować malloc/free/calloc/realloc etc z niektórymi interposers via LD_PRELOAD. W moim małym teście tylko malloc wydaje się być wstawiony, chociaż wykryto free (patrz dane wyjściowe).LD_PRELOAD działa tylko dla malloc, nie za darmo

Spodziewam się, że dane wyjściowe będą zawierały wiersz "NANO: wolny (x)" - ale brakuje tej linii.

Biorąc

// 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); 
} 

I

// 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; 
} 

Rzeczywista moc wynosi:

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

Odpowiedz

9

Jesteś kompilacji C++; oznacza to, że (domyślnie) funkcje są wymieniane na nazwy, aby pasowały do ​​ABI C++. Niestety, funkcje, które próbujesz przechwycić, to , a nie zawikłane nazwami, więc w końcu podpinacie niewłaściwą (nieistniejącą) funkcję.

Poprawka polega na: a) zdefiniowaniu obwolut w bloku extern "C" { } lub a) podaniu nagłówka funkcji - jak w #include <cstdlib>. Spowoduje to pobranie deklaracji dla malloc i free z opakowaniem extern "C", informując kompilator, aby nie mantował nazwy.

Powodem malloc prace prawdopodobnie dlatego <stdio.h> lub <dlfcn.h> ściąga deklaracji dla mallocale niefree. Tak więc, malloc jest niezmieniony, ale free jest zmanipulowany.

Uwaga: jeśli używasz glibc, powinieneś używać malloc hooks do przechwytywania funkcji przydzielania pamięci. glibc robi jakieś dziwne rzeczy z wersjami symboli, które mogą zakłócać twoje haki. Przykład użycia go znajduje się w dokumentacji połączonej - nie zapomnij o extern "C" s jeśli używasz C++, choć!

+0

Argh mangling nazwy. Spot na miejscu. Oznacza to, że wszystkie przykłady, których używałem, gdzie C/gcc. Powinienem się zorientować, kiedy poszedłem do g ++. Dzięki za podpowiedź - na razie wolę ocenić prostą technikę LD_PRELOAD. Nie jestem pewien żadnych zalet haczyków malloc. – Justicle

+0

@bdonian, jeśli grasz Mam pytanie uzupełniające tutaj: http://stackoverflow.com/questions/7910666/problems-with-ld-preload-and-calloc-interposition-for-certain-executables – Justicle

Powiązane problemy