DYLD_LIBRARY_PATH & DYLD_INSERT_LIBRARIES ne fonctionne pas

Je crée un fichier .dylib et le comstack:

#define _GNU_SOURCE #include  #include  static void* (*real_malloc)(size_t); void *malloc(size_t size) { void *p = NULL; fprintf(stderr, "malloc(%zd) = ", size); p = real_malloc(size); fprintf(stderr, "%p\n", p); return p; } void __atsortingbute((constructor))init() { real_malloc = (decltype(real_malloc))dlsym(RTLD_NEXT, "malloc"); if (NULL == real_malloc) { fprintf(stderr, "Error in `dlsym`: %s\n", dlerror()); return; } } 

Ensuite, je crée un programme de test qui appelle malloc . Je me suis assuré que l’appel à malloc n’est pas optimisé.

Ensuite, j’ai couru ce qui suit:

DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest

Il le charge mais il n’accroche PAS la fonction du tout. Des idées? J’ai essayé ce code avant la mise à niveau d’El Capitan et il fonctionnait auparavant .. J’ai également fait en sorte que le malloc lève une exception juste pour voir s’il était appelé. Ce n’est pas.

Qu’est-ce que je rate?

Les résultats ont été:

 sh-3.2# DYLD_PRINT_LIBRARIES=1 X=1 DYLD_INSERT_LIBRARIES=./libTestHook.dylib ./malloctest clear dyld: loaded: /Users/Brandon/Desktop/./malloctest dyld: loaded: ./libTestHook.dylib dyld: loaded: /usr/lib/libc++.1.dylib dyld: loaded: /usr/lib/libSystem.B.dylib dyld: loaded: /usr/lib/libc++abi.dylib dyld: loaded: /usr/lib/system/libcache.dylib dyld: loaded: /usr/lib/system/libcommonCrypto.dylib dyld: loaded: /usr/lib/system/libcomstackr_rt.dylib dyld: loaded: /usr/lib/system/libcopyfile.dylib dyld: loaded: /usr/lib/system/libcorecrypto.dylib dyld: loaded: /usr/lib/system/libdispatch.dylib dyld: loaded: /usr/lib/system/libdyld.dylib dyld: loaded: /usr/lib/system/libkeymgr.dylib dyld: loaded: /usr/lib/system/liblaunch.dylib dyld: loaded: /usr/lib/system/libmacho.dylib dyld: loaded: /usr/lib/system/libquarantine.dylib dyld: loaded: /usr/lib/system/libremovefile.dylib dyld: loaded: /usr/lib/system/libsystem_asl.dylib dyld: loaded: /usr/lib/system/libsystem_blocks.dylib dyld: loaded: /usr/lib/system/libsystem_c.dylib dyld: loaded: /usr/lib/system/libsystem_configuration.dylib dyld: loaded: /usr/lib/system/libsystem_coreservices.dylib dyld: loaded: /usr/lib/system/libsystem_coretls.dylib dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib dyld: loaded: /usr/lib/system/libsystem_info.dylib dyld: loaded: /usr/lib/system/libsystem_kernel.dylib dyld: loaded: /usr/lib/system/libsystem_m.dylib dyld: loaded: /usr/lib/system/libsystem_malloc.dylib dyld: loaded: /usr/lib/system/libsystem_network.dylib dyld: loaded: /usr/lib/system/libsystem_networkextension.dylib dyld: loaded: /usr/lib/system/libsystem_notify.dylib dyld: loaded: /usr/lib/system/libsystem_platform.dylib dyld: loaded: /usr/lib/system/libsystem_pthread.dylib dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib dyld: loaded: /usr/lib/system/libsystem_secinit.dylib dyld: loaded: /usr/lib/system/libsystem_trace.dylib dyld: loaded: /usr/lib/system/libunc.dylib dyld: loaded: /usr/lib/system/libunwind.dylib dyld: loaded: /usr/lib/system/libxpc.dylib dyld: loaded: /usr/lib/libobjc.A.dylib dyld: loaded: /usr/lib/libauto.dylib dyld: loaded: /usr/lib/libDiagnosticMessagesClient.dylib A B C D 

    Le code de mon message original fonctionnait auparavant sur Yosemite. Sur El Capitan, cela ne fonctionne pas. J’ai fini par suivre l’approche suivante ( DYLD_INTERPOSE + DYLD_INSERT_LIBRARIES ):

     #define _GNU_SOURCE #include  #include  #include  #define DYLD_INTERPOSE(_replacment,_replacee) \ __atsortingbute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \ __atsortingbute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee }; void* pMalloc(size_t size) //would be nice if I didn't have to rename my function.. { printf("Allocated: %zu\n", size); return malloc(size); } DYLD_INTERPOSE(pMalloc, malloc); 

    De dyld docs:

    DYLD_INSERT_LIBRARIES Ceci est une liste de bibliothèques dynamics à charger précédant celles spécifiées dans le programme, séparées par des deux-points. Cela vous permet de tester de nouveaux modules de bibliothèques partagées dynamics existantes utilisées dans les images d’espace de noms plat en chargeant une bibliothèque partagée dynamic temporaire uniquement avec les nouveaux modules. Notez que cela n’a aucun effet sur les images construites avec des images d’espace de nom à deux niveaux à l’aide d’une bibliothèque partagée dynamic, sauf si DYLD_FORCE_FLAT_NAMESPACE est également utilisé.

    DYLD_FORCE_FLAT_NAMESPACE Forcer toutes les images du programme à être liées en tant qu’images d’espace de noms plates et ignorer les liaisons d’espace de noms à deux niveaux. Cela peut empêcher les programmes de s’exécuter avec une erreur de symbole défini multiple si des images d’espace de noms à deux niveaux sont utilisées pour permettre aux images d’avoir des symboles définis multiples.

    Donc, votre code avait besoin de DYLD_FORCE_FLAT_NAMESPACE = 1. Quoi qu’il en soit, mon implémentation fonctionne pour /usr/local/bin/git uniquement avec cette option activée.

    Si vous pouvez recomstackr l’exécutable en cours de connexion, je pense qu’une solution plus simple consiste à recomstackr l’exécutable avec -force_flat_namespace :

     ➜ clang slow_leak.c -force_flat_namespace -o slow_leak ➜ DYLD_INSERT_LIBRARIES=malloc_hook.dylib ./slow_leak leaking in hooked malloc 

    Plus d’infos Ceci est sur OSX 10.12.2 MacOS Sierra.