Opção GCC-fPIC

li sobre as opções do GCC para as Convenções de Geração de códigos , mas não consegui entender o que "Gerar Código independente de posição (PIC)" faz. Por favor, dê um exemplo para me explicar o que significa.

Author: Hauke Rehfeld, 2011-03-15

6 answers

Código independente de posição significa que o código da máquina gerada não depende de estar localizado em um endereço específico para funcionar.

Por exemplo, os saltos seriam gerados como relativos em vez de absolutos.

Pseudo-montagem:

PIC: isto funcionaria se o código estivesse no endereço 100 ou 1000

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL CURRENT+10
...
111: NOP

Não PIC: isto só funcionará se o código estiver no endereço 100

100: COMPARE REG1, REG2
101: JUMP_IF_EQUAL 111
...
111: NOP

Editar: em resposta ao comentário.

Se o seu código for compilado com - fPIC, é adequado para inclusão em uma biblioteca - a biblioteca deve ser capaz de ser realocada de seu local preferido na memória para outro endereço, pode haver outra biblioteca já carregada no endereço que sua biblioteca prefere.

 399
Author: Erik, 2014-10-08 00:04:14
Vou tentar explicar o que já foi dito de uma forma mais simples.

Sempre que é carregada uma lib partilhada, o carregador (o código no SO que carrega qualquer programa que executar) muda alguns endereços no código, dependendo de onde o objecto foi carregado.

No exemplo acima, o " 111 " no código não PIC é escrito pelo carregador da primeira vez que foi carregado.

Para objetos não compartilhados, você pode querer que seja assim porque o compilador pode fazer algumas otimizações nesse código.

Para um Objecto partilhado, se outro processo quiser " ligar "a esse código, deve lê-lo para os mesmos endereços virtuais ou o" 111 " não fará sentido. mas esse espaço virtual pode já estar em uso no segundo processo.

 45
Author: Roee Gavirel, 2017-01-18 17:47:51

O código que é incorporado em bibliotecas compartilhadas deve normalmente ser um código independente da posição, de modo que a biblioteca compartilhada possa ser prontamente carregada em (mais ou menos) qualquer endereço na memória. A opção -fPIC garante que o GCC produz esse código.

 30
Author: Jonathan Leffler, 2011-03-15 12:25:13

Adicionar mais...

Todo processo tem o mesmo espaço de endereço virtual (se a aleatorização de endereço virtual é interrompida usando uma bandeira no Linux OS) (Para mais detalhes desactivar e activar de novo a aleatorização do espaço de endereços apenas para mim)

Então se o seu único exe sem ligação partilhada (cenário hipotético), então podemos sempre dar o mesmo endereço virtual para a mesma instrução asm sem nenhum dano.

Mas quando queremos ligar o Objecto partilhado ao exe, não têm a certeza do endereço inicial atribuído ao Objecto partilhado, uma vez que irá depender da ordem em que os Objectos Partilhados foram ligados.Dito isto, a instrução asm dentro. assim, terá sempre um endereço virtual diferente dependendo do processo a que está ligado.

Assim, um processo pode dar o endereço inicial para. de modo que 0x45678910 no seu próprio espaço virtual e outro processo ao mesmo tempo pode dar o endereço inicial de 0x12131415 e se eles não usam endereçamento relativo,. assim, não irá funcionar em todo.

Então eles sempre têm que usar o modo de endereçamento relativo e, portanto, a opção fpic.

 16
Author: Ritesh, 2017-05-23 12:02:47

O link para uma função numa biblioteca dinâmica é resolvido quando a Biblioteca é carregada ou em tempo de execução. Portanto, tanto o arquivo executável e biblioteca dinâmica são carregados na memória quando o programa é executado. O endereço de memória no qual uma biblioteca dinâmica é carregada não pode ser determinado em avançar, porque um endereço fixo pode colidir com outra biblioteca dinâmica que requer o mesmo endereço.


Existem dois métodos habitualmente utilizados para lidar com este problema: problema:

1.Mudanca. Todos os ponteiros e endereços no código são modificados, se necessário, para caber o endereço de carga real. A mudança é feita pelo linker e pelo carregador.

2.Código independente. Todos os endereços no código são relativos à posição atual. Objetos compartilhados em sistemas Unix-like usam código independente de posição por padrão. Isto é menos eficiente do que realocação se o programa correr por um longo tempo, especialmente no modo 32-bit.


O nome " posição-código independente " na verdade implica o seguinte:

  • A secção de código não contém endereços absolutos que necessitem de realocação, mas apenas Auto-relativos. endereco. Portanto, a seção de código pode ser carregada em um endereço de memória arbitrário e compartilhada entre vários processos.

  • A seção de dados não é compartilhada entre vários processos porque muitas vezes contém dados graváveis. Portanto, a seção de dados pode conter ponteiros ou endereços que preciso de recolocação.

  • Todas as funções públicas e dados públicos podem ser sobrepostos no Linux. Se uma função no executável principal tem o mesmo nome que uma função em um objeto compartilhado, então o a versão principal terá precedência, não só quando chamado do main, mas também quando chamada do Objecto partilhado. Da mesma forma, quando uma variável global em geral tem o mesmo nome como uma variável global no objeto compartilhado, então a instância em main será usado, mesmo quando acessado a partir do compartilhado objecto.


Esta assim chamada interposição de Símbolos tem a intenção de imitar o comportamento das bibliotecas estáticas.

Um Objecto partilhado tem uma tabela de ponteiros para as suas funções, chamada tabela de ligação do procedimento (PLT) e uma tabela of pointers to its variables called global offset table (GOT) in order to implement this "override" feature. Todos os acessos a funções e variáveis públicas passam por estas tabelas.

P. S. onde a ligação dinâmica não pode ser evitada, existem várias maneiras de evitar as características timeconsumantes do Código posição-independente.

Pode ler mais deste artigo: http://www.agner.org/optimize/optimizing_cpp.pdf

 7
Author: bruziuz, 2016-11-24 11:30:44

Uma pequena adição às respostas já publicadas: os ficheiros de objectos não compilados para serem independentes da posição são relocalizáveis; contêm entradas na tabela de relocalização.

Estes itens Permitem ao carregador (aquele bit de código que carrega um programa na memória) reescrever os endereços absolutos para ajustar o endereço de carga real no espaço de endereço virtual.

Um sistema operativo irá tentar partilhar uma única cópia de uma" biblioteca de Objectos Partilhados " carregada na memória com todos os programas que estão ligadas à mesma biblioteca de objetos compartilhados.

Uma vez que o espaço de endereçamento de código (ao contrário das seções do espaço de dados) não precisa ser contíguo, e porque a maioria dos programas que ligam a uma biblioteca específica tem uma árvore de dependências de biblioteca bastante fixa, isso acontece a maior parte do tempo. Nesses casos raros em que há uma discrepância, sim, pode ser necessário ter duas ou mais cópias de uma biblioteca de objetos compartilhados em memória.

Obviamente, qualquer tentativa de randomizar o endereço de carga de um a biblioteca entre programas e/ou instâncias de programas (de modo a reduzir a possibilidade de criar um padrão explorável) tornará esses casos comuns, não raros, de modo que quando um sistema ativou essa capacidade, deve-se fazer todas as tentativas de compilar todas as bibliotecas de Objetos Compartilhados para ser independente da posição.

Uma vez que as chamadas para estas bibliotecas do corpo do programa principal também serão feitas relocalizáveis, isso faz com que seja muito menos provável que uma biblioteca compartilhada tenha que ser copiada.

 4
Author: user1016759, 2016-07-15 21:48:08