O que significam as várias versões do GLIBC na saída do ldd?

2

O programa ldd relata algumas bibliotecas compartilhadas ausentes que minha biblioteca compartilhada precisa. (Eu o construí em uma máquina diferente com o Red Hat Linux 7 e quero executá-lo em outro com o Red Hat Linux 6.)

Na seção "informações da versão" abaixo, há três entradas para libc.so.6; cada um tem uma versão diferente entre parênteses depois (GLIBC_2.14, GLIBC_2.4 e GLIBC_2.2.5). A primeira delas não possui uma biblioteca compartilhada associada instalada na máquina.

Sou novo no Linux e não entendo como interpretar essa saída, quanto mais resolver o problema. Abaixo está o comando e a saída.

>ldd -v libAtlasUtilsPB.so
./libAtlasUtilsPB.so: /lib64/libc.so.6: version 'GLIBC_2.14' not found (required by ./libAtlasUtilsPB.so)
./libAtlasUtilsPB.so: /usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.18' not found (required by ./libAtlasUtilsPB.so)
./libAtlasUtilsPB.so: /usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.15' not found (required by ./libAtlasUtilsPB.so)
    linux-vdso.so.1 =>  (0x00007fffa3dff000)
    librt.so.1 => /lib64/librt.so.1 (0x00007fea7a7b2000)
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fea7a4ab000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fea7a227000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fea7a011000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fea79df3000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fea79a5f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fea7ad17000)

    Version information:
    ./libAtlasUtilsPB.so:
            libgcc_s.so.1 (GCC_3.0) => /lib64/libgcc_s.so.1
            libm.so.6 (GLIBC_2.2.5) => /lib64/libm.so.6
            libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0
            libc.so.6 (GLIBC_2.14) => not found
            libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
            libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
            libstdc++.so.6 (GLIBCXX_3.4.18) => not found
            libstdc++.so.6 (GLIBCXX_3.4.15) => not found
            libstdc++.so.6 (GLIBCXX_3.4.9) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (GLIBCXX_3.4.11) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (CXXABI_1.3) => /usr/lib64/libstdc++.so.6
            libstdc++.so.6 (GLIBCXX_3.4) => /usr/lib64/libstdc++.so.6
    
por Tones 26.07.2018 / 19:10

1 resposta

3

ldd lista as bibliotecas compartilhadas que seu argumento requer. Com a opção -v , lista todas as informações disponíveis, incluindo símbolos de versão.

Linhas do formulário

linux-vdso.so.1 =>  (0x00007fffa3dff000)
librt.so.1 => /lib64/librt.so.1 (0x00007fea7a7b2000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fea7a4ab000)

liste as bibliotecas exigidas por libAtlasUtilsPB.so e como elas são resolvidas; no seu caso, todas as bibliotecas necessárias são encontradas. linux-vdso.so.1 é especial, é uma uma biblioteca virtual fornecida pelo kernel.

Linhas do formulário

libgcc_s.so.1 (GCC_3.0) => /lib64/libgcc_s.so.1
libm.so.6 (GLIBC_2.2.5) => /lib64/libm.so.6
libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0

liste os símbolos de versão exigidos por libAtlasUtilsPB.so e, novamente, como eles são resolvidos. É aqui que ldd não consegue resolver os itens, o que indica ambos indicando "não encontrado" aqui e imprimindo mensagens de erro no início de sua saída.

GLIBC_... , GLIBCXX_... etc. são símbolos de versão, que são usados em algumas bibliotecas (incluindo a biblioteca GNU C e as bibliotecas do GCC) para identificar as versões necessárias e gerenciar a compatibilidade com versões anteriores. Um binário (executável ou biblioteca) geralmente acabará exigindo várias versões, com base nos símbolos que ele realmente usa da biblioteca de destino. Para satisfazer os requisitos de um dado binário, você precisa fornecer uma biblioteca que suporte todas as versões necessárias - ou seja, uma biblioteca que corresponda pelo menos ao símbolo da versão mais alta na lista de requisitos.

O motivo pelo qual várias versões podem acabar sendo necessárias é que cada objeto importado (função etc.) pode ter uma versão e um determinado binário pode vincular-se a várias versões em todas as funções que ele usa. Por exemplo, escolhendo um exemplo com duas versões no meu sistema, /lib/x86_64-linux-gnu/libgcc_s.so.1 , ldd -v mostra

/lib/x86_64-linux-gnu/libgcc_s.so.1:
        libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6

libgcc_s.so.1 precisa de dois símbolos de versão de libc.so.6 . Para descobrir o porquê, precisamos examinar os símbolos indefinidos que contém - estes são os símbolos que ele precisa importar:

$ objdump -T /lib/x86_64-linux-gnu/libgcc_s.so.1|grep -F '*UND*'
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 dl_iterate_phdr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000  w   D  *UND*  0000000000000000              __pthread_key_create
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strlen
0000000000000000  w   D  *UND*  0000000000000000              pthread_getspecific
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memset
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 calloc
0000000000000000  w   D  *UND*  0000000000000000              pthread_key_create
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14  memcpy
0000000000000000  w   D  *UND*  0000000000000000              pthread_once
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 pthread_mutex_unlock
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 malloc
0000000000000000  w   D  *UND*  0000000000000000              pthread_setspecific
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 realloc
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 pthread_mutex_lock

Isso lista vários símbolos com versão (aqueles com GLIBC_2.2.5 ou GLIBC_2.14 na segunda e última coluna), e podemos ver aqui que as versões correspondem àquelas que vimos com ldd . Por que acabamos com vários símbolos de versões? É aqui que entra a compatibilidade com versões anteriores. A versão 2.2.5 é a linha de base para o versionamento de símbolos na biblioteca GNU C; qualquer função que estava presente na versão 2.2.5 carrega essa versão. Na versão 2.13 da biblioteca GNU C, o comportamento de memcpy foi alterado; isso quebrou vários programas, portanto, na versão 2.14, uma versão compatível com versões anteriores foi implementada com a tag opcional GLIBC_2.2.5 version e uma nova versão adicionada com a tag GLIBC_2.14 version. Portanto, binários antigos construídos com versões anteriores da biblioteca C usam a versão antiga de memcpy e binários criados com a versão 2.14 e posterior usam a nova versão de memcpy .

A mesma história se aplica a libstdc++.so.6 , mas com muitas outras alterações com números de versão atualizados; o manual libstdc++ fornece detalhes .

No seu caso, você precisa de libstdc++.so.6 matching GLIBCXX_3.4.18 , ou seja, a versão fornecida pelo GCC 4.8.0 ou posterior, e a versão 2.14 da biblioteca GNU C.

Você não pode criar facilmente binários no RHEL 7 e executá-los no RHEL 6 (é por isso que a versão principal é diferente). Seria melhor reconstruir seu programa no RHEL 6 ...

    
por 26.07.2018 / 19:43