Como o próprio vinculador / carregador dinâmico pode ser vinculado dinamicamente conforme relatado por `file`?

12

Considere as dependências de objetos compartilhados de /bin/bash, que incluem /lib64/ld-linux-x86-64.so.2(vinculador / carregador dinâmico):

ldd /bin/bash
    linux-vdso.so.1 (0x00007fffd0887000)
    libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f57a04e3000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f57a04de000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f57a031d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f57a0652000)

A inspeção /lib64/ld-linux-x86-64.so.2mostra que é um link simbólico para /lib/x86_64-linux-gnu/ld-2.28.so:

ls -la /lib64/ld-linux-x86-64.so.2 
lrwxrwxrwx 1 root root 32 May  1 19:24 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.28.so

Além disso, os filerelatórios /lib/x86_64-linux-gnu/ld-2.28.sosão dinamicamente vinculados:

file -L /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

Eu gostaria de saber:

  1. Como o próprio linker / loader ( /lib64/ld-linux-x86-64.so.2) dinamicamente pode ser vinculado dinamicamente? Ele se vincula em tempo de execução?
  2. /lib/x86_64-linux-gnu/ld-2.28.soestá documentado para manipular a.out binários ( man ld.so), mas /bin/bashé um ELF executável?

O programa ld.so lida com binários a.out, um formato usado há muito tempo; O ld-linux.so * (/lib/ld-linux.so.1 para libc5, /lib/ld-linux.so.2 para glibc2) identifica o ELF, que todo mundo usa há anos.

Shuzheng
fonte
O kernel não se importa com essas sutilezas taxonômicas (e você também não deve ;-)). O kernel apenas faz a diferença entre ELFs que precisam de um intérprete e aqueles que não precisam . E o AFAIK, você não pode usar um intérprete que precise dele.
mosvy
@StephenKitt mine não tem ( /lib/x86_64-linux-gnu/ld-2.28.so, debian 10 buster)
mosvy
@mosvy sim, desculpe, eu me envolvi no filecomentário errado de como ele define binários estáticos e a realidade de ld-2.28.so... O diferencial é PT_DYNAMIC.
Stephen Kitt

Respostas:

17
  1. Sim, ele se liga quando é inicializado. Tecnicamente, o vinculador dinâmico não precisa de resolução e realocação de objetos, pois é totalmente resolvido como está, mas define símbolos e precisa cuidar deles ao resolver o binário que está "interpretando", e esses símbolos são atualizados para apontar para suas implementações nas bibliotecas carregadas. Em particular, isso afeta malloc- o vinculador possui uma versão mínima integrada, com o símbolo correspondente, mas é substituída pela versão da biblioteca C quando carregada e realocada (ou mesmo por uma versão interposta, se houver), com algum cuidado tomadas para garantir que isso não aconteça em um ponto em que possa interromper o vinculador.

    Os detalhes sangrentos estão rtld.c, nodl_main função.

    Observe no entanto que ld.sonão possui dependências externas. Você pode ver os símbolos envolvidos nm -D; nenhum deles é indefinido.

  2. A página de manual refere-se apenas às entradas diretamente em /lib, ie /lib/ld.so (o vinculador dinâmico libc 5, que suporta a.out) e /lib*/ld-linux*.so*(o vinculador dinâmico libc 6, que suporta ELF). A página de manual é muito específica e ld.sonão é ld-2.28.so.

    O vinculador dinâmico encontrado na grande maioria dos sistemas atuais não inclui a.outsuporte.

filee lddrelata coisas diferentes para o vinculador dinâmico porque elas têm definições diferentes do que constitui um binário vinculado estaticamente. Pois ldd, um binário está estaticamente vinculado se não tiver DT_NEEDEDsímbolos, ou seja , sem símbolos indefinidos. Pois file, um binário ELF é estaticamente vinculado se não tiver uma PT_DYNAMICseção (isso será alterado na versão file5.37 a seguir; agora usa a presença de uma PT_INTERPseção como o indicador de um binário vinculado dinamicamente, que corresponde ao comentário em o código).

O vinculador dinâmico da biblioteca GNU C não possui DT_NEEDEDsímbolos, mas possui uma PT_DYNAMICseção (já que é tecnicamente uma biblioteca compartilhada). Como resultado, ldd(que é o vinculador dinâmico) indica que ele está vinculado estaticamente, mas fileindica que ele está vinculado dinamicamente. Ele não possui uma PT_INTERPseção, portanto, a próxima versão do filetambém indicará que está vinculada estaticamente.

$ ldd /lib64/ld-linux-x86-64.so.2
        statically linked

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(com file5.35)

$ file $(readlink /lib64/ld-linux-x86-64.so.2)
/lib/x86_64-linux-gnu/ld-2.28.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f25dfd7b95be4ba386fd71080accae8c0732b711, stripped

(com a versão atualmente em desenvolvimento de file).

Stephen Kitt
fonte
Por que a palavra "interpretação" é usada no contexto da vinculação dinâmica? Essa palavra é geralmente usada no contexto de linguagens de programação.
Shuzheng
O que você quer dizer com "vinculador dinâmico da biblioteca GNU C"? Você está se referindo a /lib*/ld-linux*.so*um terceiro vinculador dinâmico?
Shuzheng
Onde você pode ver os lddrelatórios do vinculador dinâmico como vinculado estaticamente? Porque sua lista de dependências de objetos compartilhados está vazia?
Shuzheng
Os programas vinculados dinamicamente precisam de algum trabalho feito antes que possam ser executados; esse trabalho é realizado pelo vinculador dinâmico, que acaba desempenhando uma função semelhante a um intérprete - ele interpreta as tabelas de realocação etc. para produzir algo que o computador possa executar.
Stephen Kitt
Quando digo "vinculador dinâmico da biblioteca GNU C", refiro-me à implementação incluída na biblioteca GNU C, normalmente enviada como /lib*/ld-linux*.so*. Especifiquei a origem do vinculador dinâmico porque existem outras implementações disponíveis para Linux.
Stephen Kitt
0
  1. Suspeito que o fileprograma esteja errado sobre o vinculador / carregador dinâmico ser vinculado dinamicamente. O lddprograma não concorda. Pelo menos não no meu sistema (Debian Stretch):

    ldd /lib/x86_64-linux-gnu/ld-2.24.so
        statically linked
    
  2. man ld.sotambém lê: "ld-linux.so * lida com ELF" . No seu sistema (e também no meu também), ambos são links simbólicos para o mesmo binário que deduzi que é capaz de lidar com o ELF e o formato a.out (obsoleto antigo).

Hkoof
fonte
que informações você adiciona à resposta aceita?
miracle173
2
@ miracle173 esta resposta é mais antiga que a resposta aceita ;-).
Stephen Kitt
você está certo. Eu perdi isso. Eu pensei que a pergunta e a resposta aceita eram muito antigas e essa resposta foi publicada nas últimas horas. Não posso desfazer meu voto negativo até que alguém modifique a postagem.
miracle173