2010-09-28 15 views
3

J'ai construit un petit patch pour ajouter à une certaine application et tracer les invocations de certaines fonctions. Parmi eux, malloc() et open(). J'utilise dlsym pour stocker le pointeur sur le symbole original et remplacer le nom de la fonction par le mien. Il compile - et fonctionne - parfaitement sous Linux. Voici le code:Ansi C patch utilisant dlsym compile OK sous Linux mais échoue sur Mac OS X

#define _GNU_SOURCE 
#include <stdint.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdarg.h> 
#include <dlfcn.h> 

/** 
* Interponemos nuestra funcion open 
* 
* @param char* filename 
* @param int  flags 
**/ 

int open(char * filename, int flags) 
{ 
    static int (*real_open)(char*, int) = NULL; 
    if (!real_open) 
     real_open = dlsym(RTLD_NEXT, "open"); 

    // Entero 
    int p = real_open(filename, flags); 
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags); 

    // Devolvemos 
    return p; 
} 

//-------------------------------------------------------- 

/** 
* Interponemos nuestra funcion malloc 
* 
* @param size_t size 
*/ 

void* malloc(size_t size) 
{ 
    static void* (*real_malloc)(size_t) = NULL; 
    if (!real_malloc) 
     real_malloc = dlsym(RTLD_NEXT, "malloc"); 

    void *p = real_malloc(size); 

    // Memoria reservada 
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p); 

    // Devolvemos 
    return p; 
} 

Puis, je le compile avec l'instruction suivante, créant un pi.so.

gcc -Wall -O2 -fPIC -shared -ldl -o pi.so pi.c 

Ensuite, j'utilise la directive LD_PRELOAD pour l'injecter dans n'importe quelle application.

LD_PRELOAD=/home/.../injection/pi.so <binary> 

Et ça fonctionne merveilleusement sous Linux! Mais quand je rentre à la maison et essaie de le compiler en utilisant GCC sous Mac, il ne compile pas et la directive LD_PRELOAd ne fonctionne pas. Que devrais-je changer? Merci beaucoup.

+0

Juste pour que vous le savez, il y avait un rectificatif technique publié au travail autour du fait que C ne définit pas le comportement pour la conversion d'un pointeur de vide à un pointeur de fonction . Voir l'exemple sur la page POSIX pour [dlsym] (http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html) pour voir comment l'utiliser de manière conforme. – dreamlax

Répondre

1

Mac OS X (10.6.4) ne contient aucune référence à LD_PRELOAD. Il est donc ignoré et votre tentative d'interposition échoue. Tout le monde n'est pas la même chose que Linux.

En regardant à travers les pages de manuel, j'ai trouvé:

$ man dyld 

...

DYLD_INSERT_LIBRARIES Ceci est une liste séparée des deux points bibliothèques dynamiques pour charger avant que celles spécifiées dans le programme . Cela vous permet de tester de nouveaux modules de bibliothèques partagées dynamiques existantes qui sont utilisées dans les images d'espace de noms en chargeant une bibliothèque partagée dynamique temporaire avec uniquement les nouveaux modules. Notez que cela n'a aucun effet sur les images construites avec des images d'espace de noms à deux niveaux utilisant une bibliothèque dynamique à moins que DYLD_FORCE_FLAT_NAMESPACE soit également utilisé.

1

Pour OSX, vous devez utiliser l'environnement d'environnement DYLD_INSERT_LIBRARIES. variable au lieu de LD_PRELOAD.

Cependant, je suis à peu près certain que vous n'obtiendrez pas l'overriding au travail. La chose la plus proche que je peux trouver est que vous aurez à faire quelques tours de montage magiques, qui quelqu'un a soigneusement emballés dans le code sous mach_override ici: http://extendamac.svn.sourceforge.net/viewvc/extendamac/trunk/code/

+0

Salut :-) Vraiment? Est-ce compliqué sous mac os x? J'ai téléchargé mach_override et j'étudie le code source mais je ne comprends pas encore comment l'utiliser. Le paquet ne contient pas de documentation textuelle: P Merci quand même. Tous les exemples d'utilisation sont les bienvenus: P – flaab

+0

http://github.com/rentzsch/mach_star semble être plus facile – flaab

4

Sur mach, vous devez utiliser DYLD_INSERT_LIBRARIES macro au lieu de LD_PRELOAD spécifier une liste de bibliothèques partagées à pré-charger (1 ... *).

Par défaut, les fonctions standard ne sont pas remplacées par les fonctions des objets partagés simplement parce qu'elles portent le même nom. Vous devez indiquer explicitement quelle fonction remplace ce qui utilise la macro DYLD_INTERPOSE. Il vous permet de déclarer une fonction de remplacement avec n'importe quel nom (par exemple, remplacer open par my_open) et d'appeler la fonction d'origine que vous remplacez. En plus de cela, vous n'avez pas à résoudre manuellement les adresses des fonctions réelles.

Alternativement, pour obtenir un comportement de type Linux, vous devez définir une macro DYLD_FORCE_FLAT_NAMESPACE.

Il se passe beaucoup plus de choses, voir le manuel dyld pour plus de détails.

Donc, votre code devrait ressembler à ceci:

#define _GNU_SOURCE 
#include <stdint.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdarg.h> 
#include <dlfcn.h> 
#include <mach-o/dyld-interposing.h> 

/** 
* Interponemos nuestra funcion open 
* 
* @param char* filename 
* @param int  flags 
**/ 

int my_open(char * filename, int flags) 
{ 
    // Entero 
    int p = open(filename, flags); 
    fprintf(stderr, "Abrimos %s) = %i\n", filename, flags); 

    // Devolvemos 
    return p; 
} 
DYLD_INTERPOSE(my_open, open) 

//-------------------------------------------------------- 

/** 
* Interponemos nuestra funcion malloc 
* 
* @param size_t size 
*/ 

void* my_malloc(size_t size) 
{ 
    void *p = malloc(size); 

    // Memoria reservada 
    fprintf(stderr, "Reserva de memoria (%d) = %p\n", size, p); 

    // Devolvemos 
    return p; 
} 
DYLD_INTERPOSE(my_malloc, malloc) 
+0

Je l'ai eu de travail :-) Merci beaucoup !! Dyld est également utile pour l'interposition de classe? :) – flaab

+0

@flaab Vous êtes les bienvenus. Cela ne sera probablement pas utile pour les classes en raison du nom mangling (en fonction du nom de la classe, namespace etcetera). Techniquement, il est possible de surcharger la méthode d'une classe, mais cela serait presque impossible à supporter car le mangling de noms n'est pas standardisé. –

+0

Bonjour Vlad :) J'ai réussi à remplacer les fonctions sans problème. ce dont j'ai vraiment besoin maintenant, c'est passer outre une fonction spécifique d'une classe. – flaab