2009-05-02 4 views
57

Durante la compilazione di librerie condivise in gcc l'opzione -fPIC compila il codice come indipendente dalla posizione. C'è qualche ragione (prestazione o altro) perché non si dovrebbe compilare tutta la posizione del codice indipendente?Perché non tutto il codice è compilato in posizione indipendente?

+1

Ma la cosa più semplice non è del tutto corretta. Molte chiamate e salti di funzione usano salti relativi in ​​modo che non abbiano nemmeno bisogno di un jump table dopo essere stati spostati. – Unknown

+0

guardando il codice di assemblaggio generato sembra che l'indirizzo della funzione sia caricato dove il codice non fpic che appare è semplicemente un salto. Sto fraintendendo la tua affermazione? – ojblass

+0

@ojblass cosa intendo dire che alcuni salti sono come "saltare 50 istruzioni prima di qui" o "saltare indietro di 5 istruzioni" invece di "saltare a 0x400000". Quindi, per dire che devi caricare un indirizzo ogni volta con -fPIC non è completamente vero. – Unknown

risposta

45

aggiunge un riferimento indiretto. Con il codice indipendente dalla posizione devi caricare l'indirizzo della tua funzione e poi saltare ad esso. Normalmente l'indirizzo della funzione è già presente nel flusso di istruzioni.

+2

Scelti per semplicità. – ojblass

24

Sì, ci sono motivi di prestazioni. Alcuni accessi sono effettivamente sotto un altro livello di riferimento indiretto per ottenere la posizione assoluta nella memoria.

C'è anche il GOT (tabella di offset globale) che memorizza gli offset delle variabili globali. Per me, sembra proprio una tabella di correzione IAT, che è classificata come dipendente dalla posizione di wikipedia e poche altre fonti.

http://en.wikipedia.org/wiki/Position_independent_code

+1

Sto facendo upvoting ma seleziono l'altro per pura semplicità. – ojblass

1

Inoltre, l'hardware di memoria virtuale nella maggior parte dei processori moderni (utilizzato dai più moderni sistemi operativi) significa che un sacco di codice (tutte le app dello spazio utente, escludendo l'uso eccessivo di mmap o simili) non deve necessariamente essere indipendente dalla posizione. Ogni programma ottiene il proprio spazio di indirizzamento che pensa inizi a zero.

+0

È più semplice codificare tali applicativi in ​​questo modo? – ojblass

+3

Tuttavia, anche con un codice PIC VM-MMU è necessario assicurarsi che la stessa libreria .so venga caricata una sola volta nella memoria quando viene utilizzata da diversi eseguibili. – mmmmmmmm

14

In aggiunta alla risposta accettata. Una cosa che danneggia molto le prestazioni del codice PIC è la mancanza di "indirizzamento relativo IP" su x86. Con "Indirizzamento relativo IP" è possibile chiedere dati che sono X byte dal puntatore di istruzioni corrente. Questo renderebbe il codice PIC molto più semplice.

Salti e chiamate, sono in genere relativi EIP, quindi quelli non rappresentano un problema. Tuttavia, l'accesso ai dati richiederà un piccolo trucco in più. A volte, un registro verrà temporaneamente riservato come "puntatore di base" ai dati richiesti dal codice. Ad esempio, una tecnica comune è quella di abusare modo chiamate lavorano su x86:

call label_1 
.dd 0xdeadbeef 
.dd 0xfeedf00d 
.dd 0x11223344 
label_1: 
pop ebp   ; now ebp holds the address of the first dataword 
        ; this works because the call pushes the **next** 
        ; instructions address 
        ; real code follows 
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way 

Questa ed altre tecniche aggiungere un livello di riferimento indiretto ai dati accessi. Ad esempio, il GOT (tabella offset globale) utilizzato dai compilatori gcc.

x86-64 ha aggiunto una modalità "RIP relativo" che rende le cose un lotto più semplice.

+1

IIRC MIPS non ha anche l'indirizzamento relativo al PC, eccetto per i salti relativi –

2

Poiché l'implementazione completamente indipendente del codice di posizione aggiunge un vincolo al generatore di codice che può impedire l'utilizzo di operazioni più veloci o aggiungere ulteriori passaggi per mantenere tale vincolo.

Questo potrebbe essere un compromesso accettabile per ottenere il multiprocessing senza un sistema di memoria virtuale, in cui ci si fida dei processi per non invadere la memoria l'uno dell'altro e potrebbe essere necessario caricare una particolare applicazione in qualsiasi indirizzo di base.

In molti sistemi moderni i compromessi in termini di prestazioni sono diversi e un caricatore di trasferimento è spesso meno costoso (costa un qualsiasi codice di tempo viene caricato per la prima volta) rispetto al migliore che un ottimizzatore può fare se ha libero dominio. Inoltre, la disponibilità di spazi di indirizzi virtuali nasconde la maggior parte delle motivazioni per l'indipendenza dalla posizione in primo luogo.

21

This article spiega come funziona il PIC e lo confronta con l'alternativa - load time relocation. Penso che sia rilevante per la tua domanda.

+4

post pertinente! = Risposta – Nick

+10

@Nick: non sono d'accordo. Se aiuta il richiedente, è una risposta. Indirizzare a un articolo rilevante o due può fornire una grande quantità di informazioni. –

+3

Non ci sono conclusioni in questo post, solo un collegamento ad un articolo. Neanche un indizio sul fatto che il PIC non sia usato di default a causa di problemi di prestazioni. – Nick

1

position-independent code ha un overhead delle prestazioni sulla maggior parte dell'architettura, poiché richiede un registro aggiuntivo.

Quindi, questo è per scopo di prestazione.

0

Al giorno d'oggi il sistema operativo e il compilatore di default rendono tutto il codice come codice indipendente dalla posizione. Prova a compilare senza il flag -fPIC, il codice verrà compilato correttamente ma riceverai solo un avvertimento.Un windows simile ad iOS usa una tecnica chiamata memory mapping per ottenere questo risultato.