miércoles, 12 de enero de 2011

Gestión de bibliotecas compartidas y depuración de problemas (debug) en GNU\Linux

Hola a todos. Tras las vacaciones he creado este artículo basado en un artículo de nixCraft. He traducido al castellano la mayoría y he modificado y añadido algunas cosas para explicarlas algo mejor con objeto de que haya una mini guía en castellano sobre estos comandos tan útiles para los administradores de sistemas y los desarrolladores de aplicaciones en GNU\Linux. Espero que os sea útil. La referencia al artículo original y en Inglés está al final del documento.

Es habitual, si sois desarrolladores, que reutilicéis código fuente proporcionado por terceros. Normalmente /lib, /lib64, /usr/local/lib y otros directorios almacenan varias bibliotecas compartidas (o también llamadas librerías). Como administradores de sistemas necesitamos gestionar e instalar estas bibliotecas compartidas y para ello podremos usar estos comandos de gestión y depuración de problemas en GNU\Linux.

¿Qué es una biblioteca en un sistema operativo GNU\Linux o UNIX "like"?

Una biblioteca no es más que una colección de recursos como subrutinas, funciones, clases, valores, etc... incluidos en un fichero. Así de simple. Existen dos clases de bibliotecas:

  • Bibliotecas Estáticas: Son todos los ficheros con el siguiente formato de nombre y extensión lib*.a. Se incluyen dentro del ejecutable de la aplicación que las usa. Esto hace que el ejecutable sea de mayor tamaño que un ejecutable que usa bibliotecas dinámicas. Las bibliotecas se cargan en el programa en tiempo de compilación.
  • Bibliotecas Dinámicas: Son todos los ficheros con el siguiente formato de nombre y extensión lib*.so*. Estos ficheros no se incluyen dentro de los ejecutables de las aplicaciones y, por tanto, los ejecutables ocupan menos. A cambio, debemos disponer de los ficheros de biblioteca dinámica junto con el ejecutable para que este funcione. Los ejecutables cargan las bibliotecas en tiempo de ejecución usando ld.so o ld-linux.so. Como nota, en entornos Ms Windows, son las DLL.

Normalmente se usan las bibliotecas dinámicas para las aplicaciones actuales ya que permiten no duplicar código que se compilaría en cada aplicación que necesitara la misma biblioteca si estas fueran estáticas.

Comandos de gestión de bibliotecas en GNU\Linux

  • ldconfig: crea los enlaces y caché necesarios a las bibliotecas compartidas más recientes que se encuentren en los directorios especificados en la línea de comandos, en el archivo /etc/ld.so.conf y en los directorios de confianza (/lib, /lib64 y /usr/lib). Usa el enlazador dinámico para ello.
  • ldd: Nos dice cuales son las bibliotecas que una aplicación necesita para funcionar.
  • ltrace: Es un trazador de llamadas a bibliotecas. Nos muestra datos de lo que hace un programa dado al ejecutarse y que bibliotecas usa en la ejecución. Sirve para depurar problemas (debug). Hay otros programas similares como strace.
  • ld.so/ld-linux.so: Es el enlazador dinámico.

Ficheros Importantes

Como administradores de sistemas debemos saber el propósito de ciertos ficheros relacionados con las bibliotecas dinámicas:

  • /lib/ld-linux.so.* : Enlazador/cargador en tiempo de ejecución.
  • /etc/ld.so.conf : Archivo que contiene una lista de directorios separados por dos puntos, espacios, tabuladores, nueva linea en los que se buscan las bibliotecas.
  • /etc/ld.so.cache : Archivo que contiene una lista ordenada de bibliotecas encontradas en los directorios especificados en /etc/ld.so.conf. Este fichero está en un formato no legible por humanos y no debe ser editado. Es creado por el comando ldconfig.
  • /etc/ld.so.preload : Archivo que contiene una lista, separada por espacios, de archivos de bibliotecas compartidas ELF que serán cargadas antes del programa. Bibliotecas y una lista ordenada de bibliotecas candidatas.
  • /etc/ld.so.nohwcap : Cuando este fichero está presente, el enlazador dinámico cargará la versión no optimizada de una biblioteca incluso si la CPU soporta la versión optimizada.
  • lib*.so.version : Bibliotecas compartidas almacenadas en los directorios /lib, /usr/lib, /usr/lib64, /lib64, /usr/local/lib. Por ejemplo, en Kubuntu, /usr/lib/libapt-pkg.so.4.10.1 es una biblioteca compartida relacionada con apt-pkg y su versión es la 4.10.1.

COMANDO ldconfig

Se necesita usar ldconfig para crear, actualizar y eliminar los enlaces y caché necesarios que usa el enlazador en tiempo de ejecución ld.so de las bibliotecas dinámicas más recientes encontradas en los directorios especificados en la linea de comandos, en el archivo /etc/ld.so.conf, y en los directorios de confianza /usr/lib, /lib64 y /lib.

El comando ldconfig chequea las cabeceras y nombres de los ficheros de las bibliotecas que encuentra cuando determina cual es la versión que deberían tener sus enlaces actualizados. Este comando también crea un archivo llamado /etc/ld.so.cache que se usa para acelerar el enlazado (linking)

Ejemplos

En el ejemplo hemos instalado un nuevo grupo de bibliotecas compartidas relacionadas con GeoIP en /usr/local/lib/:

$ ls -l /usr/local/lib/

-rw-r--r-- 1 root root 878738 Jun 16  2010 libGeoIP.a
-rwxr-xr-x 1 root root    799 Jun 16  2010 libGeoIP.la
lrwxrwxrwx 1 root root     17 Jun 16  2010 libGeoIP.so -> libGeoIP.so.1.4.6
lrwxrwxrwx 1 root root     17 Jun 16  2010 libGeoIP.so.1 -> libGeoIP.so.1.4.6
-rwxr-xr-x 1 root root 322776 Jun 16  2010 libGeoIP.so.1.4.6
-rw-r--r-- 1 root root  72172 Jun 16  2010 libGeoIPUpdate.a
-rwxr-xr-x 1 root root    872 Jun 16  2010 libGeoIPUpdate.la
lrwxrwxrwx 1 root root     23 Jun 16  2010 libGeoIPUpdate.so -> libGeoIPUpdate.so.0.0.0
lrwxrwxrwx 1 root root     23 Jun 16  2010 libGeoIPUpdate.so.0 -> libGeoIPUpdate.so.0.0.0
-rwxr-xr-x 1 root root  55003 Jun 16  2010 libGeoIPUpdate.so.0.0.0

Ahora cuando ejecutemos una aplicación relacionada con libGeoIP.so, obtendremos un error sobre biblioteca no encontrada. Necesitamos ejecutar manualmente ldconfig para enlazar las bibliotecas nuevas instaladas pasándolas como argumento, mediante la opción -l, al comando ldconfig:

# ldconfig -l /ruta/a/lib/libNueva.so
# ldconfig -l /usr/local/lib/libGeoIP.so

Otra opción, y es la recomendada para los administradores de sistemas, es crear un fichero de configuración con un nombre descriptivo en el directorio /etc/ld.so.conf.d/ donde incluimos el directorio en el que se encuentran las bibliotecas instaladas:

# vim /etc/ld.so.conf.d/geoip.conf

/usr/local/lib

Guardamos el fichero y, ahora, al ejecutar ldconfig para actualizar la cache se incluirán dichas bibliotecas compartidas:

# ldconfig

Podemos verificar las nuevas bibliotecas o buscar bibliotecas enlazadas con los comandos:

# ldconfig -v
/usr/lib/nvidia-current:
        libnvidia-wfb.so.1 -> libnvidia-wfb.so.260.19.06
        libnvidia-tls.so.260.19.06 -> libnvidia-tls.so.260.19.06
        libnvidia-compiler.so.260.19.06 -> libnvidia-compiler.so.260.19.06
        libcuda.so.1 -> libcuda.so.260.19.06
        libXvMCNVIDIA_dynamic.so.1 -> libXvMCNVIDIA.so.260.19.06
        libnvidia-cfg.so.1 -> libnvidia-cfg.so.260.19.06
        libnvidia-glcore.so.260.19.06 -> libnvidia-glcore.so.260.19.06
        libGL.so.1 -> libGL.so.260.19.06
        libOpenCL.so.1 -> libOpenCL.so.1.0.0
...

# ldconfig -v | grep -i geoip
...
libGeoIP.so.1 -> libGeoIP.so.1.4.6
libGeoIPUpdate.so.0 -> libGeoIPUpdate.so.0.0.0
...

Problemática con Chrooted Jails

Como introducción, los entornos chroot se usan para crear una "jaula" para una determinada aplicación en la que se sustituye el directorio raíz solamente para dicha aplicación y sus procesos hijos. Al cambiar el directorio raíz podemos tener problemas con las bibliotecas compartidas que usa la aplicación. Para crear un entorno chroot ejecutamos el comando del mismo nombre y le damos un directorio que creamos en el sistema real que usará como nuevo directorio raíz (equivalente a /) y la aplicación que estará dentro de ese entorno.

Si se quiere ejecutar una aplicación como bash en un entorno chroot debemos tener en cuenta que bash usa bibliotecas dinámicas. Para ello deberíamos copiar el comando bash al nuevo directorio raíz, después ver con "ldd bash" una lista de las bibliotecas compartidas que necesita bash para funcionar normalmente y copiarlos en la misma ubicación que tienen en el sistema real pero dentro del directorio que usamos como raíz en el entorno chroot. Por último, también tendríamos que copiar los ficheros necesarios que el comando bash requiriera (datos, estado, ficheros de device...) en la misma ubicación que tendrían en el sistema pero dentro del nuevo directorio raíz.

Se puede imprimir la cache con la opción -p :

# ldconfig -p
938 bibliotecas se encontraron en la caché `/etc/ld.so.cache'
        libzrtpcpp-1.4.so.0 (libc6) => /usr/lib/libzrtpcpp-1.4.so.0
        libzip.so.1 (libc6) => /usr/lib/libzip.so.1
...

Algo más complejo como colocar un servidor web como Apache / Nginx / Lighttpd en un entorno o "jaula" chroot minimiza (que no evita) el daño realizado por una brecha de seguridad aislando el servidor web en una pequeña sección del sistema de ficheros. Sería necesario copiar todos los ficheros requeridos por el servidor web dentro del sistema de ficheros enjaulado en el directorio /jail, por ejemplo, incluyendo los binarios del servidor web, bibliotecas compartidas, módulos, archivos de configuración, páginas web php/perl/html... También necesitaríamos copiar los ficheros /etc/{ld.so.cache,ld.so.conf} y el directorio /etc/ld.so.conf.d/ al directorio /jail/etc/ y después usar ldconfig para actualizar, imprimir y resolver problemas con la jaula chroot.

Por ejemplo, de forma básica y suponiendo que tenemos todo lo necesario copiado a /jail de bash, el enlazador y nginx:

### Enjaulamos bash en el directorio jail.
# Ahora bash se ejecuta usando el directorio raíz / pero en realidad es /jail
###
chroot /jail /bin/bash

### Actualizamos la cache en /jail ya que ejecutamos ldconfig en el bash enjaulado ###
ldconfig

### Imprimimos la cache en /jail y vemos las bibliotecas que usa nginx, por ejemplo ###
ldconfig -p

### Copiamos todas las bibliotecas perdidas de nginx. Solo pongo un cp de ejemplo en el que se
# debería sustituir las rutas por las reales y después se comprueba que se han agregado
# con ldconfig.
###
cp /ruta/a/alguna.lib /jail/ruta/a/alguna.lib
ldconfig
ldconfig -v | grep alguna.lib

### Salimos del entorno enjaulado, es decir, del bash ###
exit

### Deberíamos eliminar bash y ldconfig de /jail para aumentar la seguridad. ###
cd /jail
rm sbin/ldconfig bin/bash

### Ahora iniciaríamos la jaula nginx (obviamente deberíamos tener todos los ficheros
# necesarios copiados)
###
chroot /jail /usr/local/nginx/sbin/nginx

Rootkits

Atendiendo a la definición de Wikipedia podemos decir que un rootkit es una herramienta, o un grupo de ellas que tiene como finalidad esconderse a sí misma y esconder otros programas, procesos, archivos, directorios, claves de registro, y puertos que permiten al intruso mantener el acceso a un sistema para remotamente realizar acciones o extraer información sensible sin conocimiento de los usuarios o administradores legítimos. Hay rootkits para diversos sistemas operativos, entre ellos, GNU\Linux y dos clases de rootkits, de núcleo (integrados en el kernel y los más peligrosos) y de aplicación

Normalmente los rootkits usan los directorios /lib, /lib64, /usr/local/lib para ocultarse de los administradores reales. Se puede usar ldconfig para ver toda la cache de todas las bibliotecas y los programas no deseados:

# /sbin/ldconfig -p | less

También podemos usar varias herramientas en GNU\Linux para detectar rootkits como chkrootkit o rkhunter.

Errores comunes

Puede que surjan los siguientes errores sobre bibliotecas dinámicas:

Dynamic linker error in foo
Can't map cache file cache-file
Cache file cache-file foo

Todos los errores anteriores significan que el enlazador de cache /etc/ld.so.cache está corrupto o no existe. Para arreglar este error simplemente hay que ejecutar ldconfig de la forma siguiente:

# ldconfig

Can't find library xyz Error

El ejecutable requiere un enlace a la biblioteca dinámica que ld.so o ld-linux.so no puede encontrar. Esto significa que una biblioteca dinámica xyz es necesaria para el programa foo y no está instalada o la ruta (path) a ella no está establecida. Para arreglar este problema hay que instalar la biblioteca xyz y establecer la ruta en /etc/ld.so.conf o crear un archivo en el directorio /etc/ld.so.conf.d/ .

COMANDO ldd

ldd (List Dynamic Dependencies) es una aplicación UNIX y GNU\Linux para mostrar las bibliotecas compartidas que requiere un programa para funcionar. Esta herramienta se requiere para construir y ejecutar varios programas servidores en un entorno o jaula chroot. Un ejemplo típico es ejecutar ldd con el servidor Apache. En kubuntu 10.10 con Apache2 instalado tenemos la siguiente salida:

$ sudo ldd /usr/sbin/apache2 
        linux-gate.so.1 =>  (0xb77c5000)
        libpcre.so.3 => /lib/libpcre.so.3 (0xb7719000)
        libaprutil-1.so.0 => /usr/lib/libaprutil-1.so.0 (0xb76fa000)
        libapr-1.so.0 => /usr/lib/libapr-1.so.0 (0xb76cc000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb76b2000)
        libc.so.6 => /lib/libc.so.6 (0xb7555000)
        libuuid.so.1 => /lib/libuuid.so.1 (0xb7550000)
        librt.so.1 => /lib/librt.so.1 (0xb7547000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0xb7515000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7510000)
        libexpat.so.1 => /lib/libexpat.so.1 (0xb74e9000)
        /lib/ld-linux.so.2 (0xb77c6000)

Ahora podemos copiar todas y cada una de esas bibliotecas compartidas al directorio /jail

# mkdir /jail/lib
# cp  /lib/libpcre.so.3 /jail/lib
# mkdir -p /jail/usr/lib
# cp /usr/lib/libaprutil-1.so.0 /jail/usr/lib
...

También podemos escribir un script bash para automatizar el proceso completo:

# Función de copia de bibliotecas compartidas
cp_support_shared_libs(){
        ## Inicializamos variables
        local d="$1"            # Directorio raíz chroot, primer argumento (/jail por ejemplo)
        local pFILE="$2"        # el archivo binario a copiar (/usr/sbin/apache2 por ejemplo)
        local files=""

 ## usamos ldd para coger la lista de bibliotecas compartidas usando AWK y sed ###
        files="$(ldd $pFILE |  awk '{ print $3 }' | sed  '/^$/d')"
 
        ## Para cada biblioteca compartida de la lista
        for i in $files
        do
          # tomamos solo el nombre del directorio
          dcc="${i%/*}"

          # si no existe el directorio en /jail lo creamos
          [ ! -d ${d}${dcc} ] && mkdir -p ${d}${dcc} 
          
          # Copiamos la biblioteca compartida (i) a la ubicación en el directorio del
          # entorno chroot
          ${_cp} -f $i ${d}${dcc}
        done
 
        # Funciona con 32 y 64 bits ld-linux
        sldl="$(ldd $pFILE | grep 'ld-linux' | awk '{ print $1}')"
        sldlsubdir="${sldl%/*}"
        [ ! -f ${d}${sldl} ] && ${_cp} -f ${sldl} ${d}${sldlsubdir}
}

Llamamos a cp_support_shared_libs() así:

cp_support_shared_libs "/jail" "/usr/sbin/apache2"

Informar de funciones no encontradas

$ ldd -d /ruta/a/ejecutable

Informar de objetos no encontrados

$ ldd -r /ruta/a/ejecutable

Determinar si una característica está soportada o no

TCP Wrapper es un sistema de ACL de red basado en host usado para filtrar el acceso de red a internet. TCP wrappers fue escrito originalmente para monitorizar y parar las actividades de crackeo sobre sistemas operativos UNIX / GNU\Linux. Para determinar cuando un ejecutable dado soporta TCP Wrapper o no podemos ejecutar el siguiente comando:

$ ldd /usr/sbin/sshd | grep libwrap
        libwrap.so.0 => /lib/libwrap.so.0 (0xb7833000)

La salida indica que el servidor openssh (sshd) de Kubuntu soporta TCP Wrapper.

Otros usos del comando ldd

Podemos usar ldd cuando un ejecutable está fallando debido a una dependencia perdida. Una vez que encuentras la dependencia perdida puedes instalarla o actualizar el cache con ldconfig como vimos antes.

COMANDO ltrace

El comando ltrace simplemente ejecuta el comando especificado hasta que este acaba de ejecutarse. Intercepta y graba todas las llamadas a bibliotecas dinámicas que fueron llamadas por el proceso ejecutado y las señales que fueron recibidas por dicho proceso. También puede interceptar e imprimir las llamadas al sistema ejecutadas por el programa. Su uso es parecido al de strace.

Ejemplos

# ltrace /usr/sbin/apache2

# ltrace /sbin/chroot /usr/sbin/apache2

$ sudo ltrace -o salida.txt ls
bin   cdrom  etc   initrd.img      lib         media  opt   root        sbin     srv  tmp  var      vmlinuz.old
boot  dev    home  initrd.img.old  lost+found  mnt    proc  salida.txt  selinux  sys  usr  vmlinuz

$ sudo less salida.txt

Vemos un trozo pequeño de la salida del comando ltrace al que pasamos el ejecutable ls y hemos guardado en salida.txt.

__libc_start_main(0x804ff80, 1, 0xbfb22aa4, 0x805a020, 0x805a010 
strrchr("ls", '/')                                                                                 = NULL
setlocale(6, "")                                                                                   = "es_ES.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale")                                                   = "/usr/share/locale"
textdomain("coreutils")                                                                            = "coreutils"
__cxa_atexit(0x80535c0, 0, 0, 0xbfb22aa4, 0xbfb229f8)                                              = 0
isatty(1)                                                                                          = 1
getenv("QUOTING_STYLE")                                                                            = NULL
getenv("LS_BLOCK_SIZE")                                                                            = NULL
getenv("BLOCK_SIZE")                                                                               = NULL
getenv("BLOCKSIZE")                                                                                = NULL
getenv("POSIXLY_CORRECT")                                                                          = NULL
getenv("BLOCK_SIZE")                                                                               = NULL
getenv("COLUMNS")                                                                                  = NULL
ioctl(1, 21523, 0xbfb229d0)                                                                        = 0
getenv("TABSIZE")                                                                                  = NULL

...

free(0x08ac2b20)                                                                                   = 
free(NULL)                                                                                         = 
free(0x08ac2b08)                                                                                   = 
exit(0 
__fpending(0xb76ac4e0, 0xb7711918, 0, 2, 0)                                                        = 0
fclose(0xb76ac4e0)                                                                                 = 0
__fpending(0xb76ac580, 0xb7711918, 0, 2, 0)                                                        = 0
fclose(0xb76ac580)                                                                                 = 0
+++ exited (status 0) +++

ltrace es una utilidad perfecta para la depuración en sistemas GNU\Linux:

  1. Monitoriza las llamadas a bibliotecas usadas por un programa y todas las señales recibidas.
  2. Para rastrear (tracking) la ejecución de un proceso.
  3. Incluso puede mostrar las llamas al sistema usadas por un programa.

Ejemplo de ltrace

Consideremos que tenemos el siguiente programa en c de ejemplo. Muy facilito, el Hola Mundo:

$ vim hello.c

#include 
int main(){
 printf("Hola Mundo\n");
 return 0;
}

Lo compilamos y ejecutamos así:

$ gcc hello.c -o hello
$ ./hello
Hola Mundo

Ahora usamos ltrace para rastrear la ejecución del programa:

$ ltrace -S -tt ./hello
22:04:52.772704 SYS_brk(NULL)                                                                      = 0x08563000
22:04:52.772839 SYS_access("/etc/ld.so.nohwcap", 00)                                               = -2
22:04:52.772923 SYS_mmap2(0, 8192, 3, 34, -1)                                                      = 0xb776b000
22:04:52.772994 SYS_access("/etc/ld.so.preload", 04)                                               = -2
22:04:52.773082 SYS_open("/etc/ld.so.cache", 0, 00)                                                = 3
22:04:52.773164 SYS_fstat64(3, 0xbfea2010, 0xb778aff4, 0xb778b8a0, 3)                              = 0
22:04:52.773225 SYS_mmap2(0, 76172, 1, 2, 3)                                                       = 0xb7758000
22:04:52.773287 SYS_close(3)                                                                       = 0
22:04:52.773328 SYS_access("/etc/ld.so.nohwcap", 00)                                               = -2
22:04:52.773417 SYS_open("/lib/libc.so.6", 0, 00)                                                  = 3
22:04:52.773494 SYS_read(3, "\177ELF\001\001\001", 512)                                            = 512
22:04:52.773567 SYS_fstat64(3, 0xbfea2064, 0xb778aff4, 0xb7768ac3, 0x804820c)                      = 0
22:04:52.773630 SYS_mmap2(0, 0x15c9a8, 5, 2050, 3)                                                 = 0xb75fb000
22:04:52.773705 SYS_mmap2(0xb7752000, 12288, 3, 2066, 3)                                           = 0xb7752000
22:04:52.773776 SYS_mmap2(0xb7755000, 10664, 3, 50, -1)                                            = 0xb7755000
22:04:52.773844 SYS_close(3)                                                                       = 0
22:04:52.773893 SYS_mmap2(0, 4096, 3, 34, -1)                                                      = 0xb75fa000
22:04:52.773957 SYS_set_thread_area(0xbfea24f8, 0xb778aff4, 0xb75fa6c0, 1, 0)                      = 0
22:04:52.774070 SYS_mprotect(0xb7752000, 8192, 1)                                                  = 0
22:04:52.774174 SYS_mprotect(0x08049000, 4096, 1)                                                  = 0
22:04:52.774223 SYS_mprotect(0xb778a000, 4096, 1)                                                  = 0
22:04:52.774267 SYS_munmap(0xb7758000, 76172)                                                      = 0
22:04:52.774344 __libc_start_main(0x80483b4, 1, 0xbfea26f4, 0x80483e0, 0x80483d0 
22:04:52.774421 puts("Hola Mundo" 
22:04:52.774499 SYS_fstat64(1, 0xbfea2520, 0xb7753ff4, 0xb77544e0, 0x8048490)                      = 0
22:04:52.774561 SYS_mmap2(0, 4096, 3, 34, -1)                                                      = 0xb776a000
22:04:52.774628 SYS_write(1, "Hola Mundo\n", 11Hola Mundo
)                                                   = 11
22:04:52.774709 <... puts resumed> )                                                               = 11
22:04:52.774740 SYS_exit_group(0 
22:04:52.774803 +++ exited (status 0) +++


Necesitamos monitorizar especialmente el orden y los argumentos de las funciones seleccionadas como open() (usada para abrir y posiblemente crear un archivo o dispositivo) o chown() (usada para cambiar la propiedad de usuario de un archivo) por tanto, podemos advertir condiciones de carrera simples o problemas relacionados con la seguridad. Esto es bastante útil, en la evaluación de la seguridad de programas binarios, para saber que clase de cambios realiza al sistema.

ltrace: Depuración de memoria y uso de I/O para clusters HA

El comando ltrace puede ser usado para rastreo del uso de memoria de las funciones malloc() y free() en programas de lenguaje C. Podemos calcular la cantidad de memoria asignada así:

$ ltrace -e malloc,free ./simulator arg1 agr2 arg3

ltrace iniciará ./simulator y rastreará las funciones malloc() y free().

Se pueden encontrar problemas de I/O así:

$ ltrace -e fopen,fread,fwrite,fclose ./simulator arg1 agr2 arg3

Puedes necesitar cambiar los nombres de funciones ya que tu plataforma UNIX o el lenguaje que estés usando puede usar nombres diferentes.

COMANDO ld.so/ld-linux.so

ld.so or / ld-linux.so se usan de la siguiente manera en GNU\Linux:

  1. Cargar las bibliotecas compartidas necesarias para la correcta ejecución de un programa.
  2. Prepara el programa para la ejecución y después lo ejecuta.

La diferencia entre ld.so y ld-linux.so es que el primero sirve para ejecutables a.out y el segundo para ejecutables ELF. Los ejecutables ELF son los más usados actualmente. Ld.so no suele usarse en los nuevos sistemas ya que solo soporta hasta la biblioteca libc

Listar todas las dependencias y como son resueltas

Vamos a los siguientes directorios:

# cd /lib

O para sistemas de 64 bits:

# cd /lib64

En Kubuntu 10.10 tenemos el enlace simbólico ld-linux.so.2 que apunta al ejecutable ld-2.12.1.so. Le damos la opción --list y el ejecutable del que queremos obtener las dependencias:

# ./ld-linux.so.2 --list /usr/sbin/apache2 
        linux-gate.so.1 =>  (0xb7778000)
        libpcre.so.3 => /lib/libpcre.so.3 (0xb76cc000)
        libaprutil-1.so.0 => /usr/lib/libaprutil-1.so.0 (0xb76ad000)
        libapr-1.so.0 => /usr/lib/libapr-1.so.0 (0xb767f000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7665000)
        libc.so.6 => /lib/libc.so.6 (0xb7508000)
        libuuid.so.1 => /lib/libuuid.so.1 (0xb7503000)
        librt.so.1 => /lib/librt.so.1 (0xb74fa000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0xb74c8000)
        libdl.so.2 => /lib/libdl.so.2 (0xb74c3000)
        libexpat.so.1 => /lib/libexpat.so.1 (0xb749c000)
        /lib/ld-linux.so.2 => ./ld-linux.so.2 (0xb7779000)


Otras opciones desde man:

--verify : verifica que el programa dado es, realmente, un objeto enlazado dinámicamente y que este enlazador puede manejarlo.

--library-path PATH : sobreescribe el valor de la variable de entorno LD_LIBRARY_PATH que hay actualmente configurada.

--inhibit-rpath LIST : ignora la información de RUNPATH y RPATH en los nombres de objetos de la lista LIST.

Variables de entorno importantes

La variable LD_LIBRARY_PATH puede usarse para configurar un conjunto de rutas donde encontrar bibliotecas dinámicas usando el formato estándar de separación mediante los dos puntos:

$ export LD_LIBRARY_PATH=/opt/simulator/lib:/usr/local/lib

La variable LD_PRELOAD permite la carga de una biblioteca que no está especificada en el ejecutable para que sea precargada.

$ export LD_PRELOAD=/home/fjbejarano/dirhard/libdirhard.so

Hay que tener en cuenta que estas variables serán ignoradas si el programa se ejecuta con los atributos setuid/setgid.

LECTURAS RECOMENDADAS (INGLÉS)

* HowTo: Debug Crashed Linux Application Core Files Like A Pro
* Debugging Tip: Trace the Process and See What It is Doing with strace
* man pages ldconfig, ld.so, ldd, ltrace
* Dynamic Linking and Loading and Shared libraries
* How to create shared library under GNU\Linux with lots of information about internal structures
* Anatomy of Linux dynamic libraries - This article investigates the process of creating and using dynamic libraries, provides details on the various tools for exploring them, and explores how these libraries work under the hood.

Referencia al artículo original
Linux Commands For Shared Library Management & Debugging Problem by Vivek Gite on January 6, 2011
Traducido al castellano, modificado y ampliado por Francisco J. Bejarano, Yo, Adminisis.
Related Posts with Thumbnails