[ << ]
[ < ]
[ Home ]
[ > ]
[ >> ]
3. Guida per riparare gli errori relativi a -fPIC
Indice:
3.a. Il Problema
Capita a volte che GCC termini con un messaggio di errore simile al seguente:
Codice 1.1: Tipico messaggio di errore di GCC |
.libs/assert.o: relocation R_X86_64_32 against `a local symbol' can not be used
when making a shared object; recompile with -fPIC .libs/assert.o: could not
read symbols: Bad value
|
Ci sono molte tipologie differenti di cause per un dato errore. Questo HOWTO
le spiegherà tutte mostrando le possibili correzioni.
3.b. Cosa è PIC?
PIC è l'abbreviazione di Position-Independent Code (ndt Codice
Indipendente dalla Posizione). Il seguente è un estratto dell'
articolo su
Wikipedia(tradotto) in merito al codice indipendente dalla posizione:
"In informatica, per codice indipendente dalla posizione (PIC,
Position-Independent Code) o eseguibile indipendente dalla posizione (PIE,
Position-Independent Executable) s'intende del codice oggetto che può essere
eseguito in differenti locazioni in memoria. Il codice PIC è comunemente usato
per librerie condivise, in modo da permettere che la stessa libreria possa
essere mappata in una locazione di memoria unica per ogni applicazione (usando
il sistema della memoria virtuale) dove non può sovrapporsi all'applicazione o
ad altre librerie condivise. Il codice PIC è stato utilizzato anche su vecchi
sistemi senza supporto MMU, in modo da permettere al sistema operativo di poter
mantenere le applicazioni reciprocamente separate.
Il codice indipendente dalla posizione può essere copiato in ogni locazione di
memoria senza modifiche ed esecuzioni, contrariamente dal codice rilocabile, che
necessità di una analisi speciale da parte di un link editor oppure di un
program loader per renderlo adatto all'esecuzione in una data locazione. Il
codice deve essere generalmente scritto o compilato in un modo particolare per
renderlo indipendente dalla posizione. Le istruzioni che riferiscono ad
indirizzi di memoria specifici, come salti assoluti, devono essere sostituite
con operazioni equivalenti ma relative al program-counter. L'indirezione
aggiuntiva può causare al codice PIC di essere meno efficiente, anche se i
moderni processori sono progettati per portare migliorie in tal senso."
—tratto da Wikipedia Encyclopaedia (traduzione dalla versione inglese)
Su alcune architetture (tra cui AMD64), le librerie condivise devono
essere "PIC-abilitate" (ndt, "PIC-enabled").
3.c. Cosa sono le "riallocazioni"?
Ancora una volta, da Wikipedia:
"In informatica, la rilocazione si riferisce al processo di sostituzione dei
riferimenti simbolici o nomi di librerie con gli attuali ed usabili indirizzi di
memoria, prima dell'esecuzione del programma stesso. Questa attività è svolta
tipicamente dal linker durante la compilazione, ma può essere svolta a tempo di
esecuzione dal program loader. I compilatori e gli assemblatori tipicamente
generano l'eseguibile con zero come indirizzo iniziale. Prima dell'esecuzione
del codice oggetto, questi indirizzi devono essere modificati in modo che
possano denotare indirizzi validi a tempo di esecuzione"
—tratto da Wikipedia Encyclopaedia (traduzione dalla versione inglese)
Con questi termini definiti, è possibile dare uno sguardo ai differenti scenari
dove possono verificarsi dei problemi:
3.d. 1° Caso: Compilatore malfunzionante (broken)
Almeno GCC 3.4 è conosciuto per avere una implementazione errata dell'opzione
-fvisibility-inlines-hidden. L'uso di questa opzione è comunque altamente
scoraggiata ed i bug relativi riportati sono solitamente marcati come "RESOLVED
INVALID". Vedere il bug 108872
per un esempio di un tipico errore causato da questa opzione.
3.e. 2° Caso: Controllo errato del supporto `-fPIC' nel "configure"
Molti strumenti configure verificano l'eventuale supporto per l'opzione
-fPIC da parte del compilatore. La verifica è eseguita compilando un
programma minimale con l'opzione -fPIC e verificando lo stderr. Se
il compilatore visualizza un qualsiasi messaggio di avvertimento (warning), è
assunto che l'opzione -fPIC non sia supportata ed è quindi abbandonata.
Sfortunatamente, se l'utente specifica una opzione inesistente (per esempio,
delle opzioni C++ in CFLAGS oppure opzioni introdotte dalle nuove
versioni di GCC ma non supportate dalle versioni precedenti), GCC visualizza in
ogni caso un messaggio di avviso ("warning"), ottenendo un malfunzionamento
della procedura di verifica.
Per evitare questo tipo di problema, i profili definiti per AMD64 usano un
bashrc che filtra le opzioni definite in C[XX]FLAGS non valide.
Vedere il bug 122208 per un
esempio.
3.f. 3° Caso: Assenza del supporto a `-fPIC' nel software da compilare
Questo è il caso più comune. È un vero bug del sistema di compilazione e
dovrebbe essere corretto nell'ebuild, preferibilmente attraverso una patch da
sottoporre agli sviluppatori originali del software. Assumendo che l'errore sia
simile a questo:
Codice 6.1: Un esempio di messaggio di errore |
.libs/assert.o: relocation R_X86_64_32 against `a local symbol' can not be used
when making a shared object; recompile with -fPIC .libs/assert.o: could not
read symbols: Bad value
|
Questo significa che il file assert.o non è stato compilato con
l'opzione -fPIC, contrariamente a come dovrebbe essere. Per la correzione
di questo tipo di errore, bisogna assicurarsi che solo gli oggetti usati nelle
librerie siano compilati con -fPIC.
In questo caso, aggiungendo globalmente -fPIC in C[XX]FLAGS si
risolverebbe il problema, ma questa pratica è scoraggiata perché anche gli
eseguibili finirebbero per essere abilitati per essere PIC.
Nota:
L'aggiunta dell'opzione -fPIC al comando di linking o in LDFLAGS
non aiuta.
|
3.g. 4° Caso: Collegare dinamicamente rispetto archivi statici
Capita qualche volta che un pacchetto possa creare delle librerie condivise
usando archivi compilati staticamente e non abilitati come PIC. Ci sono due
ragioni principali perché questo possa accadere:
Spesso è il risultato di un mix di USE=static e USE=-static. Se un
pacchetto di libreria può essere compilato staticamente impostando
USE=static, solitamente non crea un file .so ma solo un
archivio .a. Comunque, quando a GCC viene passata l'opzione
-l per collegare detta (dinamica o statica) libreria, esso ripiega
sull'archivio statico quando non può individuare la relativa libreria condivisa.
In questo caso, la soluzione preferita è la compilazione statica della libreria
usando anche l'opzione -fPIC.
Avvertenza:
Compilare gli archivi statici con l'opzione -fPIC abilitata solo su
AMD64. Su altre architetture questo non è necessario ed avrà un impatto a tempo
di esecuzione.
|
Vedere i bug 88360 e mysql 8796 per un esempio.
Qualche volta può essere il caso che una libreria non sia predisposta ad essere
una libreria condivisa, per esempio perché fa un intenso uso di variabili
globali. In questo caso la soluzione è cambiare la libreria condivisa in una
libreria statica.
Vedere il bug 131460 per un
esempio
Codice 7.1: Esempio di messaggio di errore |
gcc -fPIC -DSHARED_OBJECT -c lex.yy.c
gcc -shared -o html2txt.so lex.yy.o -lfl
usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/../../../../x86_64-pc-linux-gnu/bin/ld:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/../../../../lib64/libfl.a(libyywrap.o):
relocation R_X86_64_32 against `a local symbol' can not be used when making a
shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.1/../../../../lib64/libfl.a: could not
read symbols: Bad value
|
[ << ]
[ < ]
[ Home ]
[ > ]
[ >> ]
I contenuti di questo documento sono rilasciati sotto la licenza Creative
Commons - Attribution / Share Alike.
|