1) En Ubuntu 10.04, con OpenSSL 0.9.8:

1) En Ubuntu 10.04, con OpenSSL 0.9.8:

Estoy intentando compilar un programa progy vincularlo con la versión beta 1.0.2 de OpenSSL, creado desde el código fuente e instalado en /usr/local/ssl-1.0.2. En un sistema antiguo que usa 0.9.8, esto funciona sin demasiados problemas. En un sistema más reciente con 1.0.1 instalado, esto requiere un poco más de trabajo. Me pregunto por qué.

1) En Ubuntu 10.04, con OpenSSL 0.9.8:

Estos son los pasos que sigo para compilar y vincular con 1.0.2.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=> Sólo aparecen los archivos 0.9.8, así que agrego la ruta a los archivos 1.0.2...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0008000000008000) => /lib/i686/cmov/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0004000000000000) => /lib/i586/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0002000000000000) => /lib/i486/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /lib/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /usr/lib/libcrypto.so.0.9.8
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

Y así puedo compilar prog...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0x0083b000)

... y está correctamente vinculado con 1.0.2.

2) En Debian Wheezy, con OpenSSL 1.0.1:

Mismos pasos, diferente resultado.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0

Asimismo, agrego la ruta a 1.0.2...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

Luego intento compilar...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0 (0xb7591000)

Pero aquí no está vinculado a 1.0.2. La ruta de la biblioteca en tiempo de compilación es correcta (especificada con -L, gccde lo contrario fallaría ya que algunas funciones utilizadas progson específicas de 1.0.2), pero no la ruta en tiempo de ejecución.

3) Cómo hacer que funcione en Wheezy

Con o sin carrera ldconfig /usr/local/ssl-1.0.2/lib:

$ gcc -o prog ... -Wl,--rpath=/usr/local/ssl-1.0.2/lib -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0xb7592000)

Alternativamente, ejecute export LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/libantes de ejecutar gcc.

lo que me gustaria saber

Usando LD_DEBUG=libs ./proglo sugerido por mr.spuratic, descubrí que las rutas se buscaron en /etc/ld.so.cache. Abrí ese archivo y descubrí que el orden en que se buscan .so corresponde al resultado de ldconfig -p.

Entonces la pregunta real es:

  • ¿Por qué el archivo 1.0.2 aparece en la parte superior de la lista de ldconfig en 1) pero no en 2)? ¿Pura aleatoriedad? ¿Confusión debido a que los archivos 1.0.1 y 1.0.2 tienen el mismo sufijo? ("1.0.0")

O, dicho de otra manera,

  • ¿Por qué las banderas agregadas en 3) no son necesarias en 1)?

Respuesta1

Hay tres cosas que debe tener en cuenta al compilar/vincular con un paquete no predeterminado:

  • encabezados (generalmente CFLAGS)
  • ruta de la biblioteca en tiempo de compilación (generalmente LDFLAGS)
  • ruta de la biblioteca en tiempo de ejecución (caminovía LDFLAGS, LD_RUN_PATH, LD_LIBRARY_PATHo ld.so.conf)

No has dicho qué proges, así que no sé qué tan bien se comportará su configuración (¿o si usa autoconf?). He visto muchos que solo realizan los primeros dos pasos de manera confiable.

Durante la etapa de enlace, el orden de la ruta de la biblioteca es relevante; suponiendo que esté utilizando la cadena de herramientas GNU (gcc y binutils), probablemente pueda ver lo que sucede configurando CFLAGSantes configure(o posible directamente Makefile):

export CFLAGS="-Wl,-t"

Esto pasa la -topción de seguimiento al vinculador. Es posible que necesite agregar V=1o VERBOSE=1al comando make si solo obtiene líneas concisas "CC" y "LD" durante el make.)

En tiempo de ejecución, puede ver qué ld.sointenta configurar cuidadosamente LD_DEBUG, por ejemplo

LD_DEBUG=libs ./myprog

(o pruebe los valores de fileso symbolspara más detalles)

Para especificar los tres parámetros correctamente en el momento de la compilación, debería poder hacer:

  • export CFLAGS="-I/usr/local/ssl-1.0.2/include"
  • export LDFLAGS="-L/usr/local/ssl-1.0.2/lib -R/usr/local/ssl-1.0.2/lib"

luego reconfigure/recompile.

Está utilizando --openssldiren lugar del más convencional --prefix(recomiendo este último y también usarlo solo make install_swsi no necesita las aproximadamente 1000 páginas de manual y enlaces simbólicos que le brinda una instalación predeterminada). Esto puede ser parte del problema. Por alguna razón, se sabe que las bibliotecas .so que muestra ld.sono tienen un sufijo de versión (por ejemplo .so.1.0.2), un " " adecuado make installdebería haberlo configurado para usted (a través del link-shareddestino en el archivo principal Makefile).

La -Ropción indica al vinculador que incruste un RPATH en la salida ejecutable de la biblioteca OpenSSL específica para que no necesite depender del valor predeterminado que ld.sonormalmente proporcionaría el vinculador de tiempo de ejecución ( ). Puede modificar los binarios existentes conchrpathen cambio.

Esto es más o menos equivalente a exportar LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib. Puede leer más sobre RPATH y el RUNPATH relacionado aquí:http://blog.tremily.us/posts/rpath/

Como último recurso, podría compilar OpenSSL sin "compartido" o con "no compartido", esto le brindará bibliotecas estáticas que no tendrán este problema (pero que bien pueden tener otros problemas, por ejemplo, para usar dentro de ELF .so, causando PIC /problemas de pastel)


Según los detalles actualizados, creo que el problema es que 1.0.1 y 1.0.2beta establecen el sufijo de versión .so (SONAME) en 1.0.0. En el primer sistema con sólo 0.9.8 esto no causa problemas; en el segundo con 1.0.1 y 1.0.2, ambos con la versión 1.0.0, "el primer partido gana" según el ld.so.{conf,d}orden. Recuerde, ldel vinculador en tiempo de compilación es un programa diferente al ld.sovinculador en tiempo de ejecución y puede tener un comportamiento diferente (generalmente dando como resultado errores de símbolos o algo peor, como ha visto).

$ cd /usr/local/src/openssl/openssl/1.0.2beta1
$ readelf -a libssl.so | grep SONAME
0x0000000e (SONAME)                     Library soname: [libssl.so.1.0.0]

$ cat verchk.c
int main(int argc, char *argv[]) {
    printf("build: %s\n",OPENSSL_VERSION_TEXT);
    printf("run  : %s\n",SSLeay_version(SSLEAY_VERSION));
    return 0;
}

$ gcc -Wall  -I/usr/local/src/openssl/openssl-1.0.2-beta1/include \
    -Wl,-rpath /usr/local/src/openssl/openssl-1.0.2-beta1/ \
    -o verchk /usr/local/src/openssl/openssl-1.0.2-beta1/libcrypto.so verchk.c

$ ./verchk
build: OpenSSL 1.0.2-beta1 24 Feb 2014
run  : OpenSSL 1.0.2-beta1 24 Feb 2014

$ grep SHLIB_M...R= Makefile
SHLIB_MAJOR=1
SHLIB_MINOR=0.0

Actualizar OpenSSL-1.1 ha realizado algunos cambios a nivel de API; el código anterior no podrá compilarse con encabezados v1.1 y bibliotecas más antiguas ( undefined reference to `OpenSSL_version').

SSLeay_version()Ahora está en desuso y (según OPENSSL_API_COMPAT) se puede #defineasignar a la función API adecuada OpenSSL_version().

Respuesta2

¿La ruta de la nueva biblioteca está en uno de los archivos que contiene /etc/ld.so.conf.d? Próxima ejecución: -

#ldconfig -v

para reconstruir el caché. Si es rápido, debería ver la nueva biblioteca en la larga lista que imprime (o canalizarla a grepo less)

¿Quizás la ruta ya estaba en el primer servidor, pero no en el segundo?

información relacionada