2016-02-20 1 views
1

J'ai rencontré quelques problèmes lors de l'utilisation LD_PRELOAD pour charger mon.lib spécifié par LD_PRELOAD ne peut pas être chargé

Les étapes sont les suivantes:

  1. libtest.c:

    void fun() 
    { 
        return 
    } 
    
  2. gcc -o libtest.so libtest.c -fPIC --shared

  3. LD_PRELOAD export = pwd /libtest.so

  4. mai n.c

    extern void fun(); void main() { fun() }

  5. gcc -o principale -L. main.c -ltest

  6. Puis ldd main

    ldd main linux-vdso.so.1=>(0x00007ffff7ffd000) /home/shiyanlou/Code/libtest.so(0x00007ffff7df9000) libtest.so=>not found libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6 (0x00007ffffa29000) /lib64/ld-linux-x86-64.so.2 (0x0000555555554000)

  7. execute principale ./main il favorise: erreur lors du chargement bibliothèque partagée: libtest.so. Impossible d'ouvrir le fichier d'objet partagé: aucun fichier ou répertoire de ce type.

Je me demande pourquoi cela m'indique que libtest.so est introuvable Après avoir exporté la variable LD_PRELOAD. Cependant, j'ai aussi essayé d'utiliser LD_PRELOAD pour spécifier une lib partagée différente (pas "libc.so") pour injecter la fonction malloc, ça marche! Pourquoi LD_PRELOAD ne fonctionne que pour la bibliothèque partagée qui n'a pas été utilisée lors de la liaison ???

Répondre

1

Vous devez créer 2 versions de * .so. Un qui a un comportement par défaut et est chargé et relié dur via "-ltest".

Maintenant, construisez votre libtest.so par défaut et prouvez avec nm -B que le symbole que vous voulez intercepter est lié dynamiquement.

Maintenant construire main.c dans main.o, puis vérifier main.o avec nm pour voir aussi qu'il a une exigence de liaison insatisfaite externe sur le symbole.

Maintenant, liez ./main avec main.o et libtest.so, puis exécutez-le. Le ./main doit être exécuté avec cette copie par défaut, démontrer le comportement par défaut et afficher également le chemin correct vers le bon DSO via la commande ldd.

...

Maintenant, vous prenez l'étape pour créer la version LD_PRELOAD. Vous devez appeler cela libtest2.so. Vous n'utilisez pas le -ltest2

Le point est que celui qui a construit ./main ne connaît pas du tout libtest2.so, il n'y a pas de dépendance au lien dur.

libtest2.a donc un comportement alternatif, comme make foo() renvoie une chaîne/un nombre différent) et le but est maintenant d'intercepter cette 2ème version à l'exécution, donc la 1ère version n'est pas appelée par défaut (ou pas du tout). En utilisant l'environnement LD_PRELOAD.

LD_PRELOAD=./libtest2.so ./main

...

Bonne chance.

+0

Salut, merci pour votre aide. Je sais que votre méthode fonctionne. Mais je veux juste savoir pourquoi LD_PRELOAD ne fonctionne pas pour la lib que j'ai utilisé pour lier mon programme exécutable? – Larry

+0

Parce qu'il est déjà chargé? '-ltest' rend une dépendance DSO dure et ce n'est pas ce que LD_PRELOAD est à propos. Vous vous méprenez sur le but. Peut-être que si vous copiez un autre nom et que vous le chargez à la place. 'cp libtest.so libtest9.so' alors' LD_PRELOAD =./libtest9.so./main' Puisque 'libtest.so' est déjà chargé d'où le' /home/shiyanlou/Code/libtest.so (0x00007ffff7df9000) 'par défaut l'éditeur de liens dynamique ne chargera un DSO qu'une seule fois dans l'espace adresse du processus. En copiant le fichier, il devient un DSO différent. –

+0

Merci pour votre explication. En résumé, j'utilise 'libtest.so' pour créer une dépendance DSO, et LD_PRELOAD est également défini sur'/home/shiyanlou/Code/libtest.so'. Quand j'exécute ./main, il chargera 'libtest.so' en raison de la dépendance de DSO plutôt que LD_PRELOAD. Et puis LD_PRELOAD sera ignoré car le même DSO a déjà été chargé. En conséquence, le fichier libtest.so n'est pas chargé et './Main' n'a pas pu être exécuté. Ai-je raison? Si oui, pourquoi LD_PRELOAD s'appelle LD_PRELOAD? Ne devrait-il pas être chargé avant tout autre DSO ?? – Larry

0

J'ai copié et renommé le DSO en tant que libtest2.so et réinitialisé LD_PRELOAD au DSO renommé (avec le chemin absolu), Il a également demandé que libtest.so soit introuvable.

Je pense que la raison pour laquelle il invite ainsi est que le libtest.so qui est utilisé pour la dépendance dure n'a pas pu être chargé. C'est-à-dire que LD_PRELOAD a été chargé, mais que la dépendance dure n'a pas pu être satisfaite, donc il n'a pas pu exécuter ./main non plus. Maintenant, je peux conclure que lors de l'exécution de ./main, DSO dépendance dépendante doit être satisfaite car chaque DSO de dépendance dure doit également être chargé (bien que ce DSO doit être totalement remplacé!), Sinon il va demander que le DSO ne puisse pas être trouvé! Merci pour votre aide @Darryl Miles