Gerenciamento de versão secundária da biblioteca compartilhada

3

Eu tenho um programa simples chamado main :

#include <iostream>
#include "random.h"

int main()
{
        std::cout << "The program has started\n";
        return get_another_random_number();
}

A função get_another_random_number() está em uma nova versão de uma biblioteca compartilhada, mas apenas a versão antiga está instalada. O programa começa a ser executado, mas falha mais tarde quando a pesquisa falha; por exemplo,

$ ./main
The program has started
./main: symbol lookup error: ./main: undefined symbol: _Z25get_another_random_numberv

Isso acontecerá se, por exemplo, librandom.so.1.3.1 contiver uma função chamada get_another_random_number() , mas main for executado em um servidor que tenha apenas librandom.so.1.2.5 instalado. Essas bibliotecas diferem apenas em sua versão secundária porque a versão 1.3 é compatível com versões anteriores da versão 1.2 da biblioteca, mas 1.2 não possui a função extra.

No meu próprio exemplo, se eu executar readelf -d main | grep NEEDED , obtenho:

 0x0000000000000001 (NEEDED)             Shared library: [librandom.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Então, tudo está vinculado somente aos principais números de versão.

Para minha biblioteca compartilhada, coloquei-a em /usr/lib/ e adicionei os links simbólicos:

lrwxrwxrwx 1 root root     23 Feb  7 14:25 /usr/lib/librandom.so -> /usr/lib/librandom.so.1
lrwxrwxrwx 1 root root     27 Feb  7 14:13 /usr/lib/librandom.so.1 -> /usr/lib/librandom.so.1.2.5
-rw-r--r-- 1 root root   7696 Feb  7 14:00 /usr/lib/librandom.so.1.2.5

Entre o mantenedor da biblioteca, o desenvolvedor de aplicativos e o administrador do sistema; quem assume a responsabilidade de evitar esta falha do programa?

  • Durante a instalação de main , um erro deve ser produzido informando que a versão secundária da biblioteca atualmente instalada é muito baixa?
  • O programa deve chamar uma função especial na biblioteca para identificar a versão e verificar se a versão secundária é suficiente?
  • O carregador da biblioteca deve verificar todos os símbolos antes de o programa começar a ser executado?
  • Eu entendi errado a numeração da versão ou perdi uma configuração para verificar a versão secundária?
por wally 07.02.2018 / 23:04

1 resposta

2

Você não entendeu mal a numeração da versão, e essa é, de fato, uma área em que normalmente aparece o símbolo de pesquisa.

Quanto à responsabilidade de quem é esse, eu diria que nos sistemas modernos ele pertence a quem quer que construa o aplicativo, não a biblioteca: se você vincular o aplicativo com ld -z now (pelo menos no GNU binutils), o vinculador dinâmico resolverá todos os símbolos na inicialização e falhará cedo se algum símbolo estiver faltando (portanto, não é necessário adicionar suas próprias verificações manuais). Você pode ativar esse comportamento após vincular um programa exportando LD_BIND_NOW=1 para o ambiente (qualquer valor não vazio funciona, e isso não é específico do Linux).

Esse tipo de problema é normalmente tratado pelos sistemas de gerenciamento de pacotes: eles mantêm metadados extensos descrevendo os requisitos de versão para símbolos e geram as dependências com controle de versão apropriadas. Também é possível que os autores da biblioteca ajudem a melhorar a situação, mas isso pode exigir muito esforço; veja os símbolos da versão especial do GNU libc (os símbolos GLIBC_... que geralmente aparecem em mensagens de erro) e geralmente o tratamento completo dos símbolos com versão.

    
por 07.02.2018 / 23:25