Quando o vinculador gera um executável (ou outra biblioteca compartilhada), ele procura por bibliotecas solicitadas usando -l
prefixando lib
e sufixando .so
com o nome. Por exemplo, se você solicitar -lcrypto
, ele pesquisará libcrypto.so
.
Após a biblioteca ser encontrada, o linker lê um metadado da biblioteca chamado seu soname. O soname é então gravado no executável que está sendo construído e esse é o nome que será usado para pesquisar a mesma biblioteca novamente em tempo de execução. O soname pode, é claro, ser diferente do nome sob o qual a biblioteca foi encontrada na hora do link.
O caso de uso para esse recurso é a capacidade de ter várias versões incompatíveis de uma biblioteca instalada no sistema ao mesmo tempo. Aqui está como é geralmente usado.
Primeiro, deixe-me descrever o que aconteceria na ausência dessa convenção:
Os cabeçalhos de desenvolvimento ( .h
files) são acoplados a uma versão específica da biblioteca, e o arquivo .so
contém essa versão também:
/usr/include/mylibrary.h
/usr/lib/libmylibrary.so
Um aplicativo myapp
foi compilado contra essa versão da biblioteca e carrega /usr/lib/libmylibrary.so
no tempo de execução.
Mais tarde, a biblioteca é atualizada para uma nova versão. O arquivo .h
e .so
foi substituído pela nova versão. Infelizmente, a nova versão tem uma ABI incompatível.
Agora, quando myapp
é executado, ele trava ou exibe um comportamento indefinido porque foi compilado em uma versão com uma ABI, mas carregou uma versão diferente em tempo de execução.
O que acontece com a convenção do soname:
A biblioteca é instalada da seguinte forma:
/usr/include/mylibrary.h
/usr/lib/libmylibrary.so -> libmylibrary.so.1
/usr/lib/libmylibrary.so.1
E /usr/lib/libmylibrary.so.1
embutiu o mesmo soname libmylibrary.so.1
.
Quando myapp
é criado, ele localiza /usr/lib/libmylibrary.so
, mas o vinculador segue o symlink e, na verdade, carrega /usr/lib/libmylibrary.so.1
. Além disso, o soname libmylibrary.so.1
é o que realmente é gravado dentro de myapp
. Em tempo de execução, myapp
carrega /usr/lib/libmylibrary.so.1
diretamente, ignorando o link simbólico.
Mais tarde, a biblioteca é atualizada para uma nova versão com uma ABI incompatível. O arquivo .h
e .so
foi substituído pela nova versão. Um novo arquivo libmylibrary.so.2
aparece. O libmylibrary.so.1
da versão antiga é deixado em paz.
/usr/include/mylibrary.h
/usr/lib/libmylibrary.so -> libmylibrary.so.2
/usr/lib/libmylibrary.so.1
/usr/lib/libmylibrary.so.2
Agora, quando myapp
é executado, continua a carregar libmylibrary.so.1
e ainda funciona conforme o esperado. Mas se outros aplicativos novos forem instalados ou o myapp
for recompilado, o link simbólico será seguido e a nova versão será usada.
O problema que você está vendo é que, quando seu aplicativo foi vinculado, o vinculador encontrou uma biblioteca que tinha o nome de usuário libcrypto.so.1.0.0
dentro dele.
Sua cópia de libcrypto.so
foi gerada com um soname se libcrypto.so.1.0.0
?
Outra possibilidade, bastante provável aqui, é que sua cópia de libcrypto.so
não tenha um soname, mas o linker realmente encontrou e usou a versão system de libcrypto.so
(do OpenSSL ) e é aí que fica o soname.