Scripts para Linux, GNU GCC, ld, version e o formato binário ELF - Como funciona?

13

Estou tentando aprender mais sobre o controle de versão da biblioteca no Linux e como colocar tudo para funcionar. Aqui está o contexto:

- Eu tenho duas versões de uma biblioteca dinâmica que expõem o mesmo conjunto de interfaces, digamos libsome1.soe libsome2.so.

- Um aplicativo está vinculado libsome1.so.

- Este aplicativo usa libdl.sopara carregar dinamicamente outro módulo, digamos libmagic.so.

- Agora libmagic.soestá ligado contra libsome2.so. Obviamente, sem o uso de scripts de vinculador para ocultar símbolos libmagic.so, em tempo de execução, todas as chamadas para interfaces libsome2.sosão resolvidas libsome1.so. Isso pode ser confirmado verificando o valor retornado por libVersion()contra o valor da macro LIB_VERSION.

- Então, tento a seguir compilar e vincular libmagic.soum script vinculador que oculte todos os símbolos, exceto os 3 definidos libmagic.soe exportados por ele. Isso funciona ... Ou pelo menos libVersion()e os LIB_VERSIONvalores correspondem (e relata a versão 2 e não 1).

- No entanto, quando algumas estruturas de dados são serializadas em disco, notei alguma corrupção. No diretório do aplicativo, se eu excluir libsome1.soe criar um link virtual em seu lugar para apontar libsome2.so, tudo funcionará conforme o esperado e a mesma corrupção não ocorrerá.

Não posso deixar de pensar que isso pode ser causado devido a algum conflito na resolução de símbolos do vinculador em tempo de execução. Eu tentei muitas coisas, como tentar vincular libsome2.sopara que todos os símbolos sejam aliados symbol@@VER_2(sobre o qual ainda estou confuso porque o comando nm -CD libsome2.soainda lista os símbolos como symbole não symbol@@VER_2) ... Nada parece funcionar !!! Socorro!!!!!!

themoondothshine
fonte
Sua última abordagem é a que eu teria começado. E eu concordo que a corrupção é provavelmente alguma confusão de símbolo. Infelizmente eu não tenho uma resposta para você.
RobotHumans
isso pode ser melhor no SO, embora eu não o compreenda o suficiente para dizer com certeza. sinalize se você quiser que a movamos.
Xenoterracide
1
Experimente as bandeiras RTLD_LOCALe RTLD_DEEPBINDdlopen no seu aplicativo. Não tenho tempo para testar isso agora, mas deve funcionar com base na página de manual.
22711 stribika

Respostas:

13

Isso não responde exatamente à sua pergunta, mas ...

Antes de tudo, ELF é a especificação usada pelo Linux para arquivos executáveis ​​(programas), bibliotecas compartilhadas e também arquivos de objetos, que são os arquivos intermediários encontrados na compilação de software. Os arquivos de objeto terminam em .o, as bibliotecas compartilhadas terminam com .so, seguidos por zero ou mais dígitos separados por pontos, e os arquivos executáveis ​​não têm extensão normalmente.

Normalmente, existem três formulários para nomear uma biblioteca compartilhada; o primeiro formulário simplesmente termina em .so. Por exemplo, uma biblioteca chamada readline é armazenada em um arquivo chamado libreadline.so e está localizada em um de / lib, / usr / lib ou / usr / local / lib normalmente. Esse arquivo está localizado ao compilar o software com uma opção como -lreadline. -l informa ao compilador para vincular à seguinte biblioteca. Como as bibliotecas mudam de tempos em tempos, elas podem se tornar obsoletas, de modo que as bibliotecas incorporam algo chamado SONAME. O SONAME para readline pode parecer com libreadline.so.2 para a segunda versão, versão principal do libreadline. Também pode haver muitas versões secundárias do readline que são compatíveis e não exigem a recompilação do software. Uma versão secundária do readline pode ser denominada libreadline.so.2.14. Normalmente libreadline. assim, é apenas um link simbólico para a versão principal mais recente do readline, libreadline.so.2, neste caso. libreadline.so.2 também é um link simbólico para libreadline.so.2.14, que na verdade é o arquivo que está sendo usado.

O SONAME de uma biblioteca é incorporado dentro do próprio arquivo da biblioteca. Em algum lugar dentro do arquivo libreadline.so.2.14 está a string libreadline.so.2. Quando um programa é compilado e vinculado ao readline, ele procura o arquivo libreadline.so e lê o SONAME incorporado. Posteriormente, quando o programa for realmente executado, ele carregará libreadline.so.2, não apenas libreadline.so, já que esse foi o SONAME que foi lido quando foi vinculado pela primeira vez. Isso permite que um sistema tenha várias versões incompatíveis do readline instaladas e cada programa carregará a versão principal apropriada à qual foi vinculado. Além disso, ao atualizar o readline, digamos, para 2.17, eu posso instalar o libreadline.so.2.17 ao lado da biblioteca existente e, uma vez que movo o link simbólico libreadline.so.2 de libreadline.so.2.13 para libreadline.so.2.17,

penguin359
fonte