Nas strace
saídas, os caminhos para as bibliotecas que os executáveis chamam estão nas chamadas para open()
. É a chamada do sistema usada pelos executáveis que estão vinculados dinamicamente? Que tal dlopen()
? open()
não é uma ligação que eu imaginaria que teria um papel na execução de programas.
23
ld-linux
ser mapeado pelo kernel como parte daexecve
chamada do sistema.O dlopen não tem nada a ver com bibliotecas compartilhadas como você pensa nelas. Existem dois métodos para carregar um objeto compartilhado:
main
função ser chamada e configurará o espaço de processo do aplicativo para que o aplicativo encontre as funções da biblioteca. Isso envolveopen()
o lubrificante emmap()
, em seguida, o mesmo, seguido da configuração de algumas tabelas de pesquisa.libdl
, a partir do qual você (usando o primeiro método) pode chamar odlopen()
edlsym()
funções. Com o dlopen, você obtém um identificador para a biblioteca, que pode ser usado com o dlsym para receber um ponteiro de função para uma função específica. Esse método é muito mais complicado para o programador do que o primeiro (já que você precisa fazer a instalação manualmente, em vez de o vinculador fazer automaticamente por você), e também é mais frágil (já que você não obtém a compilação -time verifica se você está chamando funções com os tipos de argumentos corretos, conforme você começa no primeiro método), mas a vantagem é que você pode decidir qual objeto compartilhado carregar no tempo de execução (ou mesmo se deve carregá-lo), tornando essa é uma interface destinada à funcionalidade do tipo plug-in. Finalmente, a interface dlopen também é menos portátil do que o contrário, pois sua mecânica depende da implementação exata do vinculador dinâmico (portanto, o libtool'slibltdl
, que tenta abstrair essas diferenças).fonte
Hoje, a maioria dos sistemas operacionais usa o método para bibliotecas compartilhadas introduzido no final de 1987 pelo SunOS-4.0. Este método é baseado no mapeamento de memória via mmap ().
Dado o fato de que, no início dos anos 90, a Sun doou o antigo código baseado em a.out (o Solaris naquela época já era baseado em ELF) ao pessoal do FreeBSD e que esse código foi posteriormente entregue a muitos outros sistemas (incluindo Linux) , você pode entender por que não há grande diferença entre plataformas.
fonte
ltrace -S
A análise de um exemplo mínimo mostra quemmap
é usado na glibc 2.23No glibc 2.23, Ubuntu 16.04, executando
latrace -S
em um programa mínimo que usadlopen
com:mostra:
então vemos imediatamente que
dlopen
chamaopen
+mmap
.A
ltrace
ferramenta impressionante rastreia chamadas de biblioteca e chamadas de sistema e, portanto, é perfeita para examinar o que está acontecendo neste caso.Uma análise mais detalhada mostra que
open
retorna o descritor de arquivo3
(o próximo é gratuito após stdin, out e err).read
então usa esse descritor de arquivo, mas os argumentos do TODO whymmap
são limitados a quatro, e não podemos ver qual fd foi usado lá, pois esse é o quinto argumento .strace
confirma como esperado que3
é esse, e a ordem do universo é restaurada.Almas corajosas também podem se aventurar no código glibc, mas não consegui encontrar o
mmap
após um grep rápido e sou preguiçoso.Testado com este exemplo mínimo com build clichê no GitHub .
fonte
strace
relatórios sobre chamadas do sistema (ou seja, funções implementadas diretamente pelo kernel). Bibliotecas dinâmicas não são uma função do kernel;dlopen
faz parte da biblioteca C, não do kernel. A implementação dedlopen
irá chamaropen
(que é uma chamada do sistema) para abrir o arquivo da biblioteca para que possa ser lido.fonte
ltrace
.ltrace -S
é perfeito para analisar isso como ele também mostra syscalls: unix.stackexchange.com/a/462710/32558