1) No Ubuntu 10.04, com OpenSSL 0.9.8:

1) No Ubuntu 10.04, com OpenSSL 0.9.8:

Estou tentando compilar um programa proge vinculá-lo ao beta 1.0.2 do OpenSSL, criado a partir do código-fonte e instalado em /usr/local/ssl-1.0.2. Em um sistema mais antigo usando 0.9.8, isso funciona sem muitos problemas. Em um sistema mais recente com 1.0.1 instalado, isso requer um pouco mais de trabalho. Estou me perguntando por quê.

1) No Ubuntu 10.04, com OpenSSL 0.9.8:

Aqui estão as etapas que sigo para compilar e vincular ao 1.0.2.

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

=> Apenas os arquivos 0.9.8 aparecem, então adiciono o caminho para os arquivos 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

E assim posso 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)

... e está corretamente vinculado ao 1.0.2.

2) No Debian Wheezy, com OpenSSL 1.0.1:

Mesmas etapas, resultados diferentes.

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

Da mesma forma, adiciono o caminho para 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

Aí eu tento 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)

Mas aqui não está vinculado ao 1.0.2. O caminho da biblioteca em tempo de compilação está correto (especificado com -L, gcccaso contrário falharia, pois algumas funções usadas progsão específicas para 1.0.2), mas não o caminho em tempo de execução.

3) Como fazer funcionar no Wheezy

Com ou sem corrida 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)

Como alternativa, execute export LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/libantes de executar o gcc.

O que eu gostaria de saber

Usando LD_DEBUG=libs ./progconforme sugerido por mr.spuratic, descobri que os caminhos foram pesquisados ​​em /etc/ld.so.cache. Abri esse arquivo e descobri que a ordem em que .so é pesquisado corresponde à saída de ldconfig -p.

Então a questão real é:

  • Por que o arquivo 1.0.2 fica no topo da lista do ldconfig em 1) mas não em 2)? Pura aleatoriedade? Confusão devido aos arquivos 1.0.1 e 1.0.2 terem o mesmo sufixo? ("1.0.0")

Ou, dito de forma diferente,

  • Por que os sinalizadores adicionados em 3) não são necessários em 1)?

Responder1

Há três coisas que você precisa cuidar ao compilar/vincular um pacote não padrão:

  • cabeçalhos (geralmente CFLAGS)
  • caminho da biblioteca em tempo de compilação (geralmente LDFLAGS)
  • caminho da biblioteca em tempo de execução (caminhoatravés de LDFLAGS, LD_RUN_PATH, LD_LIBRARY_PATHou ld.so.conf)

Você não disse o que progé, então não sei quão bem comportada sua configuração pode ser (ou se usa autoconf?). Já vi muitos que executam apenas as duas primeiras etapas de maneira confiável.

Durante o estágio de link, a ordem do caminho da biblioteca é relevante, supondo que você esteja usando o conjunto de ferramentas GNU (gcc e binutils), você provavelmente poderá ver o que está acontecendo configurando CFLAGSantes configure(ou possível diretamente Makefile):

export CFLAGS="-Wl,-t"

Isso passa a -topção de rastreamento para o vinculador. Você pode precisar adicionar V=1ou VERBOSE=1ao comando make se você obtiver apenas linhas concisas "CC" e "LD" durante o make.)

Em tempo de execução você pode ver o que ld.sotenta definindo cuidadosamente LD_DEBUG, por exemplo

LD_DEBUG=libs ./myprog

(ou tente valores de filesou symbolspara mais detalhes)

Para especificar todos os três parâmetros corretamente no momento da construção, você deve ser capaz de fazer:

  • 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"

em seguida, reconfigure/recompile.

Você está usando --openssldirem vez do mais convencional --prefix(eu recomendo o último e também usando apenas make install_swse você não precisar das cerca de 1000 páginas de manual e links simbólicos que uma instalação padrão oferece). Isso pode ser parte do problema. Por alguma razão, sabe-se que as bibliotecas .so que você mostra ld.sonão possuem um sufixo de versão (por exemplo, .so.1.0.2), um " " adequado make installdeveria ter configurado isso para você (por meio do link-shareddestino no main Makefile).

A -Ropção instrui o vinculador a incorporar um RPATH na saída executável da biblioteca OpenSSL específica para que ele não precise depender do padrão que o vinculador de tempo de execução ( ld.so) normalmente forneceria. Você pode modificar binários existentes comchrpathem vez de.

Isto é mais ou menos equivalente a exportar LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib. Você pode ler mais sobre RPATH e o RUNPATH relacionado aqui:http://blog.tremily.us/posts/rpath/

Como último recurso, você poderia construir OpenSSL sem "shared" ou com "noshared", isso fornecerá bibliotecas estáticas que não terão esse problema (mas podem ter outros problemas, por exemplo, para uso dentro do ELF .so, causando PIC /problemas de TORTA)


Com base nos detalhes atualizados, acredito que o problema é que 1.0.1 e 1.0.2beta definem o sufixo de versão .so (SONAME) como 1.0.0. No primeiro sistema com apenas 0.9.8 isso não causa problemas; no segundo, com 1.0.1 e 1.0.2, ambos versionados como 1.0.0, são "vitórias na primeira partida" com base na ld.so.{conf,d}ordem. Lembre-se de que ldo vinculador em tempo de compilação é um programa diferente do ld.sovinculador em tempo de execução e pode ter um comportamento diferente (geralmente resultando em erros de símbolo ou pior, como você viu).

$ 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

Atualizar OpenSSL-1.1 fez algumas alterações no nível da API, o código acima não será compilado com cabeçalhos v1.1 e bibliotecas mais antigas ( undefined reference to `OpenSSL_version').

SSLeay_version()agora está obsoleto e (dependendo de OPENSSL_API_COMPAT) pode ser #define-d para a função de API adequada OpenSSL_version().

Responder2

O caminho da nova lib está em um dos arquivos dentro /etc/ld.so.conf.d? Próxima execução: -

#ldconfig -v

para reconstruir o cache. Se você for rápido, deverá ver a nova lib na longa lista impressa (ou canalizá-la para grepou less)

Talvez o caminho já estivesse no primeiro servidor, mas não no segundo?

informação relacionada