A biblioteca de links dinâmicos deve ser carregada na RAM

0

Como sabemos, qualquer arquivo executável, que esteja sendo executado, é carregado na RAM.

Além disso, temos dois tipos de libs: biblioteca de links estáticos e biblioteca de links dinâmicos.

Os dois tipos de libs também devem ser carregados na RAM enquanto são necessários.

Como eu sei, temos duas maneiras de carregar a biblioteca dinâmica:

  1. vinculá-lo durante a compilação, como g++ -lsofile
  2. carregar dinamicamente no código, temos dlopen para fazer isso

Eu publiquei esta pergunta mas posso Ainda não se esqueça de que poderíamos listar todos os arquivos lib. Para o primeiro caso acima, acho que podemos obter o arquivo de link com ldd ou verificar /proc/{PID}/maps . Mas, para o segundo caso, estou pensando se posso obter os arquivos de link com algum método, aqui está um exemplo:

void SomeModule()
{
    //dlopen here to link mysofile
}

int main()
{
    if (user_enter == 'a')
    {
        printf("hello world");
    }
    else
    {
        SomeModule();
    }
}

Neste exemplo, quando o executamos e digitamos sempre a , o dlopen nunca será chamado, portanto, mysofile nunca será vinculado, o que significa que mysofile nunca será carregado na RAM. Estou certo?

Se sim, como posso obter os arquivos lib necessários do arquivo executável, exceto ler o código-fonte?

    
por Yves 09.03.2018 / 09:35

2 respostas

1

Você tem razão, se dlopen nunca for chamado, a biblioteca de destino nunca será carregada na memória (do processo).

Determinar as bibliotecas necessárias sem ler o código-fonte parece uma variante do problema de parada. Você poderia usar algumas heurísticas: se o programa não estiver vinculado a libdl , ele não poderá usar dlopen ; Em caso afirmativo, você pode usar strace (consulte Como descobrir as cargas de executáveis de bibliotecas dinâmicas durante a execução? ) ou tente descobrir os argumentos para dlopen usando a análise estática. Mas o programa poderia incluir libdl diretamente (por meio de link estático ou pela construção do código); e como o vinculador dinâmico não é mágico, não há nada que impeça um programa de reimplementá-lo, portanto, você não pode ter absolutamente certeza de ter encontrado todas as bibliotecas necessárias usando essas heurísticas. Talvez existam programas que descubram que estão sendo rastreados e pule o carregamento de bibliotecas ...

A única forma segura de listar todas as bibliotecas necessárias é ler o código-fonte.

    
por 09.03.2018 / 09:52
2

As we know, any executable file, which is running, is loaded into RAM.

Errado!

um arquivo executável é mapeado no espaço de endereço virtual de processos executados, pelo virtual memory do kernel. A RAM física é gerenciada apenas pelo kernel. Leia Sistemas operacionais: três peças fáceis para saber mais.

Nem todo o segmento de código desse arquivo executável recebe paginado (não carregado! ) na RAM. Em particular, um grande pedaço de código que nunca é usado (por exemplo, porque contém alguma função grande que nunca é chamada) não irá para a RAM. Leia sobre o paging e a página cache .

Às vezes, não há RAM física suficiente para lidar convenientemente com todas as páginas necessárias. Nessa situação, você observa se debatendo .

o vinculador dinâmico (consulte ld-linux (8) ) e também dlopen (3) usa mmap(2) para mapear alguns segmentos da biblioteca compartilhada. Portanto, ele não carrega todo o segmento de código do plug-in na RAM. Leia também o documento Como escrever bibliotecas compartilhadas do Drepper

when we execute it and type always a, the dlopen will never be called, so mysofile will never be linked, which means that mysofile will never be loaded into RAM.

absolutamente de jeito nenhum em geral para prever quais bibliotecas compartilhadas futuras seriam usadas e dlopen -ed. Pense nos dois cenários a seguir:

  • um programa de longa duração (talvez o seu navegador) pede ao seu usuário para obter alguma biblioteca compartilhada (talvez baixá-lo da rede) e então dlopen it.

  • um processo está gerando algum código C em um arquivo temporário /tmp/emittedcode.c , compila (por fork um processo apropriado executando algum gcc -O -Wall -fPIC /tmp/emittedcode.c -shared -o /tmp/emittedcode.so ) esse arquivo em um plugin temporário /tmp/emittedcode.so e dlopen -s esse plugin temporário (claro que depois dlsym -os símbolos apropriados lá).

Eu gosto muito da segunda abordagem. Observe que compilação para C é um hábito bem estabelecido. E os compiladores atuais são rápidos o suficiente para permitir que isso seja feito em alguma interação do REPL.

BTW, em um desktop Linux, um processo pode usar dlopen muitos objetos compartilhados , isto é, plugins (pelo menos centenas de milhares e provavelmente milhões). Veja meu exemplo manydl.c (que gera código C "aleatório" em arquivos temporários e repita).

PS. Esteja ciente também do Problema de Interrupção , relacionado à impossibilidade teórica de prever todos os caminhos dlopen -ed futuros.

    
por 09.03.2018 / 11:10