2012-04-20 1 views
7

ldd est un bon moyen simple de vérifier les bibliothèques partagées qu'un exécutable donné utilise ou utilisera. Cependant, cela ne fonctionne pas toujours comme prévu. Par exemple, voir l'extrait shell suivante qui montre comment il « ne » pour fonder la libreadline « dépendance » dans le binaire pythonvérification des bibliothèques partagées pour les chargeurs non par défaut

J'ai essayé beaucoup d'autres distributions, mais je copie de Tikanga

$ lsb_release -a 
LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch 
Distributor ID: RedHatEnterpriseServer 
Description: Red Hat Enterprise Linux Server release 5.6 (Tikanga) 
Release:  5.6 
Codename:  Tikanga 

Voir ce que ldd fait sur le python installé par défaut (à partir des dépôts officiels).

$ which python 
/usr/bin/python 
$ ldd `which python` 
    libpython2.4.so.1.0 => /usr/lib64/libpython2.4.so.1.0 (0x00000030e6200000) 
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030e0e00000) 
    libdl.so.2 => /lib64/libdl.so.2 (0x00000030e0a00000) 
    libutil.so.1 => /lib64/libutil.so.1 (0x00000030ee800000) 
    libm.so.6 => /lib64/libm.so.6 (0x00000030e0600000) 
    libc.so.6 => /lib64/libc.so.6 (0x00000030e0200000) 
    /lib64/ld-linux-x86-64.so.2 (0x00000030dfe00000) 
$ ldd `which python` | grep readline 
$ 

Rien trouvé à propos de readline. Maintenant, je sais par l'utilisation interactive que ce binaire a des fonctionnalités réelles, alors n'essayons pas de voir d'où il vient.

$ python & 
[1] 21003 
$ Python 2.4.3 (#1, Dec 10 2010, 17:24:35) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 

[1]+ Stopped     python 

Commencer une session interactive de python en arrière-plan (pid 21003)

$ lsof -p 21003 
COMMAND PID USER FD TYPE DEVICE  SIZE NODE NAME 
python 21003 ddvento cwd DIR 0,33 16384 164304 /glade/home/ddvento/loader-test 
python 21003 ddvento rtd DIR 8,3  4096  2/
python 21003 ddvento txt REG 8,3  8304 6813419 /usr/bin/python 
python 21003 ddvento mem REG 8,3 143600 8699326 /lib64/ld-2.5.so 
python 21003 ddvento mem REG 8,3 1722304 8699327 /lib64/libc-2.5.so 
python 21003 ddvento mem REG 8,3 615136 8699490 /lib64/libm-2.5.so 
python 21003 ddvento mem REG 8,3 23360 8699458 /lib64/libdl-2.5.so 
python 21003 ddvento mem REG 8,3 145824 8699445 /lib64/libpthread-2.5.so 
python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 
python 21003 ddvento mem REG 8,3 15840 8699446 /lib64/libtermcap.so.2.0.8 
python 21003 ddvento mem REG 8,3 1244792 6833317 /usr/lib64/libpython2.4.so.1.0 
python 21003 ddvento mem REG 8,3 18152 8699626 /lib64/libutil-2.5.so 
python 21003 ddvento mem REG 8,3 56446448 6832889 /usr/lib/locale/locale-archive 
python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so 
python 21003 ddvento mem REG 8,3 25464 6901074 /usr/lib64/gconv/gconv-modules.cache 
python 21003 ddvento 0u CHR 136,1    3 /dev/pts/1 
python 21003 ddvento 1u CHR 136,1    3 /dev/pts/1 
python 21003 ddvento 2u CHR 136,1    3 /dev/pts/1 
$ lsof -p 21003 | grep readline 
python 21003 ddvento mem REG 8,3 247544 6821551 /usr/lib64/libreadline.so.5.1 
python 21003 ddvento mem REG 8,3 21808 6965997 /usr/lib64/python2.4/lib-dynload/readline.so 

Bingo! Ici c'est readline!

Cependant, cette technique ne fonctionne que lorsque la bibliothèque est effectivement chargée, donc par exemple, il ne trouve pas /usr/lib64/libtcl8.4.so jusqu'à ce que le processus de python ne fonctionne pas quelque chose comme from Tkinter import *

J'ai donc deux questions:

  1. Je crois que le problème avec ldd est qu'il suppose l'utilisation du chargeur standard, alors que très probablement python utilise son propre chargeur spécial (de sorte que vous ne devez pas relier l'exécutable chaque fois que vous installez un nouveau module python n'est pas pur python mais a un certain c/C++/fortran code). Est-ce correct? De toute évidence, si un exécutable utilise son propre chargeur, il n'y a pas de réponse évidente à la question «comment trouver toutes les bibliothèques possibles que cet exécutable peut charger»: cela dépend de ce que fait le chargeur. Mais existe-t-il un moyen de savoir quelles bibliothèques peuvent être chargées par python?

PS: lié à 1. Si vous êtes à l'atterrissage sur cette question que vous devriez déjà savoir ce qui suit, mais si vous ne devriez pas: voir comment simple est de complètement gâcher ldd sortie (Messing it up uniquement en partie est un peu plus difficile):

$ cat hello.c 
#include <stdio.h> 

int main() { 
    printf("Hello world.\n"); 
    return 0; 
} 

$ gcc -static hello.c -o loader 
$ gcc -Wl,--dynamic-linker,./loader hello.c -o hello 
$ ./hello 
Hello world. 
$ ldd ./hello 
Hello world. 

Répondre

5

Python, Perl et autres langages interprétés font des choses de charge dynamiquement à l'aide dlopen(). (Ce n'est pas la même chose que de remplacer le chargeur standard, ils l'utilisent encore, et en fait dlopen() est un crochet dans le chargeur standard sur les systèmes ELF.)

Il n'y a pas de registre standard pour les modules chargeables. Python utilise ses propres règles pour déterminer d'où les modules d'extension peuvent être chargés (voir sys.path), y compris ceux qui ont des objets partagés associés. Perl utilise des règles différentes. Apache utilise des règles encore différentes, etc.

Donc, pour résumer les réponses à vos questions:

  1. pas exactement

  2. pas

+0

Ok, merci, j'ai légèrement modifié votre réponse et l'ai accepté. – Davide

0

Comme une note de côté, un moyen possible d'accomplir ce que je voulais en question 2 serait:

  • créer un vide chroot

  • python recompilation là-dedans, en ajoutant manuellement tout ce qui manque, un par un

En fonction de vos objectifs, cela pourrait ou pourrait ne pas être une bonne solution (et en fait s'avère pas trop mal pour ce que mes objectifs sont - étrange que cela puisse paraître de la question)

Questions connexes