Como o processo conhece o endereço da biblioteca compartilhada?

2

Até onde eu sei, quando eu compilo meu código-fonte C, o GCC / LD faz a ligação do endereço em tempo de compilação. Normalmente, esse endereço começa em zero. Quando eu chamo uma função da biblioteca compartilhada como o compilador sabe o endereço da biblioteca compartilhada com antecedência? Eu sei que bibliotecas compartilhadas obtêm seu endereço em tempo de carregamento. Por favor, corrija-me se estiver errado.

    
por Saber 27.10.2015 / 11:10

1 resposta

1

Você pode fazer algumas coisas para ajudar a entender isso.

ldd /usr/bin/cat

No meu laptop, isso gera essa saída:

1771 % ldd /usr/bin/cat 
        linux-vdso.so.1 (0x00007ffc37fba000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f1ea7018000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f1ea73bc000)

Você notará que linux-vdso.so.1 e libc.so.6 não têm um caminho totalmente qualificado e que ldd mostra a você o caminho real que seria usado para vincular dinamicamente em libc.so.6 .

Você pode verificar isso (e aprender um pouco) fazendo o ldd novamente, com uma pequena variação:

1790 % export LD_LIBRARY_PATH=/lib
1791 % ldd /usr/bin/cat 
        linux-vdso.so.1 (0x00007fff0a5a0000)
        libc.so.6 => /lib/libc.so.6 (0x00007fa257535000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa2578d9000)

Olhando de perto, você pode ver que o vinculador dinâmico ( /lib64/ld-linux-x86-64.so.2 neste caso) escolherá agora /lib/libc.so.6 como a biblioteca C. Portanto, a variável de ambiente LD_LIBRARY_PATH é importante para decidir quais arquivos realmente são usados na vinculação dinâmica.

A outra coisa que você pode fazer é strace :

strace -o cat.trace /usr/bin/cat /etc/motd

O arquivo cat.trace terá um registro do que o sistema chama seu processo de assunto. Alguns deles serão mmap() dos arquivos mostrados por ldd ao serem vinculados dinamicamente. Acompanhamento por googlling por mmap .

Leitura adicional: man ld.so .

Veja se você tem o comando readelf instalado ou se pode instalá-lo ou compilá-lo. Execute readelf -a /usr/bin/cat . A verdadeira especificação ELF é impenetrável na minha opinião, mas existe algum bom formato ELF informações lá fora. Tente encontrar.

Se você tem o musl libc instalado, ou pode instalá-lo, fazendo as mesmas experiências acima em um simples executável Compilado com musl libc pode ser muito informativo. Até mesmo algo tão complexo quanto a vinculação dinâmica pode ter duas implementações de trabalho diferentes no mesmo sistema operacional.

    
por 27.10.2015 / 14:33