Comprobar bibliotecas compartidas para los cargadores no predeterminados

ldd es una buena forma sencilla de verificar las bibliotecas compartidas que un ejecutable determinado está utilizando o utilizará. Sin embargo, no siempre funciona como se esperaba. Por ejemplo, vea el siguiente fragmento de shell que muestra cómo "falla" encontrar la "dependencia" de libreadline en el binario de python

He intentado muchas otras distribuciones, pero estoy copiando desde Tikanga

<code>$ 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
</code>

Mira quéldd lo hace en el predeterminado instaladopython (De repositorios oficiales).

<code>$ 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
$
</code>

No se ha encontrado nada sobre readline. Ahora sé por el uso interactivo que este binario tiene una funcionalidad real, así que no intente ver de dónde viene.

<code>$ 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
</code>

Comenzó una sesión interactiva de python en segundo plano (pid 21003)

<code>$ 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
</code>

¡Bingo! ¡Aquí está readline!

Sin embargo, esta técnica funciona solo cuando la biblioteca está cargada efectivamente, por lo que, por ejemplo, no encuentra/usr/lib64/libtcl8.4.so hasta que el proceso de python no se ejecuta algo comofrom Tkinter import *

Así que tengo dos preguntas:

Creo que el problema conldd es que asume el uso del cargador estándar, mientras que es muy probable que Python esté usando su propio cargador especial (de modo que no tenga que volver a vincular el ejecutable cada vez que instale un nuevo módulo de Python que no sea Python puro sino que tenga algo de C). / c ++ / código fortran). ¿Es esto correcto?

Claramente, si un ejecutable está utilizando su propio cargador, no hay una respuesta obvia a la pregunta "cómo encontrar todas las bibliotecas posibles que este ejecutable puede cargar": depende de lo que haga el cargador. Pero, ¿hay alguna manera de averiguar qué bibliotecas puede cargar Python?

PD: relacionado con 1. Si te estás dirigiendo a esta pregunta, ya deberías saber lo siguiente, pero si no, deberías: ver qué simple es desordenar completamenteldd salida (arruinarlo solo parcialmente es un poco más difícil):

<code>$ 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.
</code>

Respuestas a la pregunta(2)

Su respuesta a la pregunta