Por que alguns arquivos de pacotes de trabalho retornam “not found” para algumas bibliotecas da saída do ldd?

4

Estou encontrando um monte de coisas onde os pacotes de trabalho contêm arquivos em que o ldd retorna "não encontrado" para algumas bibliotecas. Por exemplo ...

/usr/lib64/thunderbird/libprldap60.so
    libldap60.so => not found

/usr/lib64/libreoffice/program/libofficebean.so
    libjawt.so => not found

Temos centenas de usuários usando o Thunderbird e o Libre Office, e ninguém relatou nenhum problema. E esses arquivos existem no sistema:

/usr/lib64/thunderbird/libldap60.so
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib/amd64/libjawt.so
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/libjawt.so

Para este exemplo, ambos / usr / bin / thunderbird e / usr / bin / libreoffice são scripts de wrapper para lançar os respectivos programas, e eu esperava que esses scripts configurassem o ambiente para que essas bibliotecas se tornassem visíveis, mas não parece que isso acontece nesses scripts.

Existem centenas de exemplos disso em todo o nosso sistema, eu escolhi esses dois exemplos. Alguém pode explicar o que está acontecendo?

    
por CptSupermrkt 10.11.2014 / 21:04

1 resposta

3

A resposta direta (talvez óbvia) é que o caminho de pesquisa das bibliotecas que você está vendo com ldd não inclui os diretórios onde as dependências da biblioteca estão localizadas. Normalmente, a menos que as dependências de uma biblioteca sejam encontradas em locais padrão do sistema, a biblioteca deve ter sido criada com um caminho de execução especificado (usando a variável de ambiente $LD_RUN_PATH ou a opção de vinculador apropriada). Caso contrário, as bibliotecas não serão encontradas mais tarde em tempo de execução, como você encontrou com ldd .

Então, por que o Thunderbird funciona mesmo assim, apesar desse "problema"?

Existem algumas maneiras pelas quais as bibliotecas necessárias podem ser encontradas de qualquer maneira, apesar do caminho de execução ausente:

  • A variável de ambiente $LD_LIBRARY_PATH é configurada no tempo de execução e fornece uma lista de diretórios adicionais para pesquisa.
  • O diretório necessário pode ter sido incluído no caminho de pesquisa porque foi encontrado no caminho de execução de alguma outra biblioteca não relacionada que foi carregada antes da atual. By the way, eu não tenho certeza se isso funciona como um acidente de implementação de se o padrão especifica isso. De um jeito ou de outro, é frágil porque depende crucialmente da ordem exata na qual as bibliotecas são carregadas.
  • A biblioteca pode ter sido carregada manualmente pelo aplicativo usando a função dlopen() com um nome de caminho completo.

O Thunderbird parece estar usando a última dessas técnicas. Eu olhei para strace output do que ele faz na inicialização e parece fazer isso:

  • Localize o diretório de onde vem seu próprio binário. Isso é sempre possível porque o assistente de script de shell que inicia o Thunderbird faz isso com um nome de caminho completo.
  • Abra o arquivo de texto dependentlibs.list encontrado nesse diretório.
  • Para cada nome de arquivo neste arquivo de texto, na ordem, prefixar o mesmo diretório para formar um nome de caminho completo e carregue-o como uma biblioteca usando dlopen() .
  • Agora, todas as bibliotecas dependentes como libldap60.so que você mencionou são "pré-carregadas" e outras bibliotecas que precisam delas não precisam encontrá-las novamente.

Observe que o pedido ou os arquivos listados em dependentlibs.list são significativos.

A razão pela qual o Thunderbird faz isso é para que o diretório onde ele está localizado não precise ser codificado no aplicativo ou no caminho de execução de qualquer uma de suas bibliotecas internas.

Eu não sei o que o Java faz, mas sem dúvida é algo similar.

    
por 10.11.2014 / 22:43