Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > f1098342ec4a2b28475e34123ce17201 > files > 294

howto-html-it-9.1-0.5mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>The Linux GCC HOWTO : Linking</TITLE>
<LINK HREF="GCC-HOWTO-7.html" REL=next>
<LINK HREF="GCC-HOWTO-5.html" REL=previous>
<LINK HREF="GCC-HOWTO.html#toc6" REL=contents>
</HEAD>
<BODY>
<A HREF="GCC-HOWTO-7.html">Avanti</A>
<A HREF="GCC-HOWTO-5.html">Indietro</A>
<A HREF="GCC-HOWTO.html#toc6">Indice</A>
<HR>
<H2><A NAME="s6">6. Linking</A></H2>

<P>Questo paragrafo &egrave; piuttosto complicato a causa dei due formati binari 
incompatibili, la distinzione tra libreria statica e condivisa, e del 
sovraccarico del verbo 'link' che significa sia 'cosa accade dopo la 
compilazione', sia 'cosa accade quando viene richiamato un programma 
compilato' (e, di fatto, il sovraccarico del verbo 'load' in un senso 
simile ma opposto).
<P>Per ridurre in qualche modo la confusione, si user&agrave; il termine 
`caricamento dinamico' (dynamic loading) per quello che accade 
durante l'esecuzione, argomento descritto nel prossimo paragrafo. 
Potrebbe anche accadere di trovare il termine 'collegamento dinamico' 
(dynamic linking) con lo stesso significato, ma non in questo 
documento. Questo paragrafo, quindi, tratta esclusivamente 
il tipo di link che avviene alla fine di una compilazione. 
<P>
<H2><A NAME="ss6.1">6.1 Librerie condivise e statiche</A>
</H2>

<P>L'ultima fase della compilazione di un programma consiste
nel 'collegamento' (link), ossia nell'unire tutte le parti e vedere se 
manca qualcosa. Ovviamente esistono alcune cose che molti 
programmi hanno in comune - ad esempio, aprire file, ed il 
codice in grado di fare queste cose sono fornite sotto forma di librerie. 
Nella maggior parte dei sistemi Linux si trovano in <CODE>/lib</CODE> e 
<CODE>/usr/lib/</CODE>.
<P>
<A NAME="index.65"></A>  
<A NAME="index.66"></A>  
<P>
<P>Quando si utilizza una libreria statica, il linker trova 
le parti necessarie ai moduli di programma e le copia 
fisicamente nel file di output eseguibile che viene 
generato. Al contrario, questo non avviene per le librerie condivise - in 
questo caso nell'output viene inserita una nota del tipo 'quando 
viene eseguito questo programma, &egrave; necessario caricare questa libreria'. 
Ovviamente, le librerie condivise tendono a creare eseguibili di 
dimensioni minori; inoltre utilizzano una quantit&agrave; inferiore di memoria e 
viene utilizzato meno spazio su disco. Il comportamento predefinito di 
Linux consiste nell'eseguire il collegamento di librerie condivise se 
esistono, altrimenti vengono utilizzate quelle statiche. Se si ottengono 
dei binari statici quando, al contrario, si vogliono quelli condivisi, 
controllare che i file di libreria condivisa (<CODE>*.sa</CODE> per a.out, 
<CODE>*.so</CODE> per ELF) si trovino dove dovrebbero essere e siano leggibili.
<P>Su Linux, le librerie statiche hanno nomi come <CODE>libname.a</CODE>, mentre 
le librerie condivise sono denominate <CODE>libname.so.x.y.z</CODE> dove 
<CODE>x.y.z</CODE> rappresenta il numero di versione. Le librerie 
condivise, inoltre, contengono spesso dei collegamenti che puntano ad 
esse, che risultano essere molto importanti, e (in configurazioni a.out) 
contengono dei file <CODE>.sa</CODE> associati. Le librerie standard 
sono disponibili sia in formato condiviso, sia in formato statico.
<P>&Egrave; possibile sapere quali librerie condivise sono richieste da un programma 
utilizzando <CODE>ldd</CODE> (List Dynamic Dependencies)
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ ldd /usr/bin/lynx
        libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
        libc.so.5 => /lib/libc.so.5.2.18
</PRE>
</CODE></BLOCKQUOTE>
<P>Questo esempio mostra che il browser WWW 'lynx' dipende dalla 
presenza di <CODE>libc.so.5</CODE> (la libreria C) e <CODE>libncurses.so.1</CODE>
(utilizzata per il controllo del terminale). Se un programma non ha 
dipendenze, <CODE>ldd</CODE> risponder&agrave; 'statically linked'
o 'statically linked (ELF)'.
<P>
<H2><A NAME="index.69"></A> <A NAME="index.68"></A> <A NAME="index.67"></A> <A NAME="ss6.2">6.2 Interrogazione delle librerie ('In quale libreria si trova sin()?')</A>
   </H2>

<P><CODE>nm</CODE> <B>nome_libreria</B> dovrebbe listare tutti i simboli per i 
quali esistono dei riferimenti in <B>nome_libreria</B>. Il comando funziona 
sia per librerie statiche che dinamiche. Si supponga di voler saper dov'&egrave; 
definita <CODE>tcgetattr()</CODE>: si potrebbe utilizzare
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ nm libncurses.so.1 |grep tcget
         U tcgetattr
</PRE>
</CODE></BLOCKQUOTE>
<P>`<CODE>U</CODE>' significa 'undefined' - mostra che la libreria <CODE>ncurses</CODE>
la utilizza ma non la definisce. In alternativa, si potrebbe usare
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ nm libc.so.5 | grep tcget
00010fe8 T __tcgetattr
00010fe8 W tcgetattr
00068718 T tcgetpgrp
</PRE>
</CODE></BLOCKQUOTE>
<P>`<CODE>W</CODE>' significa 'weak', ossia che il simbolo &egrave; definito, ma 
in modo tale da poter essere sostituito da un'altra definizione in una 
libreria diversa. Una definizione 'normale' (come quella per 
<CODE>tcgetpgrp</CODE>) &egrave; indicata con una '<CODE>T</CODE>'.
<P>
<A NAME="index.70"></A>  
<P>
<P>Comunque la risposta breve alla domanda del titolo, consiste in 
<CODE>libm.(so|a)</CODE>. Tutte le funzioni definite in <CODE>&lt;math.h&gt;</CODE>
sono tenute nella libreria <CODE>math</CODE>; ne consegue che sar&agrave; 
necessario eseguire il collegamento con l'opzione <CODE>-lm</CODE> quando si 
utilizza una di esse. 
<P>
<H2><A NAME="ss6.3">6.3 Ricerca dei file</A>
</H2>

<P><CODE>ld: Output file requires shared library `libfoo.so.1`</CODE><BR>
(Ovvero: "ld: Il file di output richiede la libreria
condivisa 'libfoo.so.1'") 
<P>La strategia di ricerca di un file per ld e simili varia a 
seconda della versione, ma l'unico punto che si pu&ograve; ritenere 
predefinito &egrave; <CODE>/usr/lib</CODE>.  Se si vuole che le librerie vengano 
cercate in altre locazioni, &egrave; necessario specificare le loro directory 
tramite l'opzione <CODE>-L</CODE> in gcc o ld.
<P>Se non dovesse funzionare, controllare che i file necessari 
si trovino effettivamente in quelle directory. Per a.out, il 
collegamento con <CODE>-lfoo</CODE> fa in modo che ld cerchi <CODE>libfoo.sa</CODE>
(condivisa) e, in caso di insuccesso, <CODE>libfoo.a</CODE> (statica). Per ELF, 
verr&agrave; eseguita la ricerca di <CODE>libfoo.so</CODE>, quindi di <CODE>libfoo.a</CODE>. 
<CODE>libfoo.so</CODE> &egrave; generalmente un collegamento simbolico a 
<CODE>libfoo.so.x</CODE>.
<P>
<H2><A NAME="ss6.4">6.4 Compilazione delle proprie librerie</A>
</H2>

<H3>Controllo della versione</H3>

<P>Come qualunque altro programma, le librerie possono contenere errori che 
vengono riscontrati e risolti nel tempo. Inoltre, le librerie possono 
introdurre nuove caratteristiche, modificare l'effetto di altre esistenti, 
o rimuovere quelle vecchie. Questo potrebbe costituire un problema per i 
programmi che le utilizzano.
<P>Pertanto si &egrave; introdutto il concetto di versione della libreria. Tutte le 
modifiche che possono essere fatte a una libreria sono catalogate
in 'minori' o 'maggiori', dove una modifica 'minore' non interrompe il
funzionamento dei vecchi 
programmi che la utilizzano. La versione di una libreria pu&ograve; essere 
dedotta dal suo nome di file (di fatto, questo non &egrave; vero per quanto 
riguarda ELF; nel seguito viene spiegato il motivo): <CODE>libfoo.so.1.2</CODE>
ha '1' come versione maggiore, e '2' come minore. Il numero di 
versione minore pu&ograve; essere svariato - libc inserisce in esso il 'livello 
di patch', assegnando alle librerie nomi del tipo <CODE>libc.so.5.2.18</CODE>, e 
spesso sono utilizzate lettere, underscore, o quasi ogni altro carattere 
ASCII. 
<P>Una delle differenze principali tra il formato ELF e a.out consiste nel 
modo in cui viene eseguita la compilazione delle librerie condivise. Per 
prima cosa viene descritto ELF, dal momento che &egrave; pi&ugrave; semplice. 
<P>
<H3><A NAME="index.71"></A> ELF. Di cosa si tratta? </H3>

<P>ELF (Executable and Linking Format) &egrave; un formato binario 
originariamente sviluppato da USL (UNIX System Laboratories) e 
attualmente utilizzato in Solaris e System V Release 4. A seguito della 
sua aumentata flessibilit&agrave; rispetto al pi&ugrave; vecchio formato a.out 
utilizzato da Linux, gli sviluppatori di librerie GCC e C 
hanno deciso lo scorso anno di utilizzare ELF come 
formato binario standard per Linux. 
<P>
<H3>Uteriori dettagli</H3>

<P>Questo paragrafo &egrave; tratto dal documento '<CODE>/news-archives/comp.sys.sun.misc</CODE>'.
<P>
<BLOCKQUOTE>
ELF (Executable Linking Format) &egrave; il nuovo e migliorato formato di file 
oggetto introdotto in SVR4. ELF &egrave; molto pi&ugrave; potente di COFF, nel fatto di 
essere estendibile dall'utente. ELF vede un file oggetto come una lista di 
sezioni arbitrariamente lunga (piuttosto che come un array di entit&agrave; a 
lunghezza fissa), tali sezioni, a differenza di quanto accade in COFF, non si 
devono trovare in un luogo specifico e non devono essere in un ordine 
specifico ecc. Gli utenti possono aggiungere nuove sezioni ai file oggetto, se 
desiderano avere a disposizione nuovi dati. ELF, inoltre, possiede un 
formato di debugging molto pi&ugrave; potente denominato DWARF (Debugging 
With Attribute Record Format) - attualmente non supportato completamente su 
Linux (ma ci si sta lavorando). Una lista linkata di DIE (o Debugging 
Information Entries) di DWARF costituisce la sezione <CODE>.debug</CODE> di ELF. 
Invece di essere un insieme di piccoli record a dimensione fissa, ogni 
DIE di DWARF contiene una lista di lunghezza arbitraria di attributi complessi 
ed &egrave; scritto come un albero di dati di programma. I DIE sono in grado di 
includere una quantit&agrave; di informazioni di molto maggiore rispetto alla sezione 
<CODE>.debug</CODE> di COFF (come grafi di eredit&agrave; del C++ ecc). 
</BLOCKQUOTE>

<BLOCKQUOTE>
L'accesso ai file ELF avviene tramite la libreria di accesso ELF SVR4 (Solaris 
2.0 ?), che fornisce un'interfaccia semplice e rapida alle parti pi&ugrave; 
complicate di ELF.  Uno dei vantaggi principali derivanti dall'utilizzo della 
libreria di accesso ELF consiste nel fatto che non sar&agrave; mai necessario vedere 
un file ELF come file Unix, &egrave; possibile eseguire l'accesso come file 
Elf *, dopo una chiamata <CODE>elf_open()</CODE> si eseguono chiamate 
<CODE>elf_foobar()</CODE> sulle sue componenti invece di occuparsi della sua immagine 
effettiva su disco (cosa che con COFF si faceva impunemente).
</BLOCKQUOTE>
 
<P>I vantaggi e gli svantaggi di ELF, e le evoluzioni necessarie per eseguire 
l'upgrade di un sistema a.out per supportarlo, sono descritti 
nell'ELF-HOWTO e non ho intenzione di ripeterli qui. L'HOWTO dovrebbe 
essere disponibile nello stesso luogo in cui &egrave; stato trovato questo 
documento. 
<P>
<H3>Librerie condivise di ELF</H3>

<P>Per eseguire la compilazione di <CODE>libfoo.so</CODE> come libreria 
condivisa, i passi di base hanno la seguente forma:
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ gcc -fPIC -c *.c
$ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o
$ ln -s libfoo.so.1.0 libfoo.so.1
$ ln -s libfoo.so.1 libfoo.so
$ LD_LIBRARY_PATH='pwd':$LD_LIBRARY_PATH ; export LD_LIBRARY_PATH
</PRE>
</CODE></BLOCKQUOTE>
<P>Questi comandi genererano una libreria condivisa denominata 
<CODE>libfoo.so.1.0</CODE>, i collegamenti appropriati per ld (<CODE>libfoo.so</CODE>) e 
il caricamento dinamico (<CODE>libfoo.so.1</CODE>) per trovarla. Per eseguire un 
collaudo, si aggiunge la directory corrente a <CODE>LD_LIBRARY_PATH</CODE>.
<P>
<A NAME="index.72"></A>  
<P>Quando si &egrave; sicuri che la libreria funziona, deve essere spostata, 
ad esempio, in <CODE>/usr/local/lib</CODE>, e devono essere creati appropriati
collegamenti. Il collegamento da <CODE>libfoo.so.1</CODE> a <CODE>libfoo.so.1.0</CODE>
&egrave; mantenuto aggiornato da <CODE>ldconfig</CODE>, che nella maggior parte dei 
sistemi viene eseguito come parte del processo di avviamento. Il
collegamento <CODE>libfoo.so</CODE> deve essere aggiornato manualmente. 
Se si &egrave; scrupolosi nell'eseguire l'aggiornamento di tutte le parti di una 
libreria (ossia degli header file) contemporaneamente, la cosa pi&ugrave; 
semplice da fare consiste nel rendere <CODE>libfoo.so -> libfoo.so.1</CODE>, 
in modo che ldconfig mantenga correnti entrambi i collegamenti. In caso 
contrario, potrebbe in seguito verificarsi ogni genere di stranezza.
<P>
<BLOCKQUOTE><CODE>
<PRE>
$ su
# cp libfoo.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libfoo.so.1 libfoo.so )
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H3><A NAME="index.74"></A> <A NAME="index.73"></A> Numerazione delle versioni, soname e symlink  </H3>

<P>Ogni libreria ha un <B>soname</B>. Quando il linker trova uno di 
questi in una libreria in cui sta eseguendo una ricerca, nel binario viene 
incluso il soname in luogo del nome di file effettivo ricercato. Durante 
l'esecuzione, il loader dinamico cercher&agrave; un file tramite il nome di 
soname, non con il nome di file/libreria. Pertanto, una libreria 
denominata <CODE>libfoo.so</CODE> potrebbe avere il soname <CODE>libbar.so</CODE>, di 
conseguenza tutti i programmi collegati ad essa, all'avvio, cercherebbero 
<CODE>libbar.so</CODE>.
<P>Sembra essere una caratteristica di poca importanza, invece &egrave; la chiave per 
capire come su un sistema possono coesistere diverse versioni della stessa 
libreria. Di fatto, la denominazione standard delle librerie in Linux 
consiste nel chiamare la libreria, ad esempio, <CODE>libfoo.so.1.2</CODE>, e 
assegnare ad essa il soname <CODE>libfoo.so.1</CODE>. Se aggiunta in una 
directory di libreria 'standard' (ossia, <CODE>/usr/lib</CODE>), 
ldconfig creer&agrave; un collegamento simbolico 
<CODE>libfoo.so.1 -> libfoo.so.1.2</CODE> in modo che sia possibile trovare 
l'immagine appropriata durante l'esecuzione. &Egrave; necessario anche un 
collegamento <CODE>libfoo.so -> libfoo.so.1</CODE> affinch&eacute; ld possa trovare 
il soname corretto da utilizzare durante il link.
<P>Pertanto, quando si risolve un errore nella libreria, o si aggiungono 
nuove funzioni (ogni modifica che non influenzi in modo negativo i 
programmi esistenti), si eseguir&agrave; nuovamente la compilazione mantenendo lo 
stesso soname, e modificando il nome di file. Quando si inseriscono 
nella libreria delle modifiche che causerebbero l'interruzione dei 
programmi esistenti, incrementare semplicemente il numero nel soname - in 
questo caso, rinominare la nuova versione <CODE>libfoo.so.2.0</CODE>, e assegnarle 
il soname <CODE>libfoo.so.2</CODE>. Quindi, convertire il collegamento a 
<CODE>libfoo.so</CODE> in modo che punti alla nuova versione e tutto &egrave; a posto.
<P>Si noti che non &egrave; <B>necessario</B> dare un nome alle librerie, ma 
si tratta di una buona convenzione. ELF fornisce una flessibilit&agrave; nel 
nominare le librerie in modi che potrebbero confondere, ma questo non 
significa che debba farlo per forza. 
<P>Riassumendo: se si suppone di osservare la tradizione secondo cui gli 
aggiornamenti maggiori potrebbero distruggere la compatibilit&agrave; e che 
quelli minori non lo fanno, eseguire il collegamento con 
<P>
<BLOCKQUOTE><CODE>
<PRE>
gcc -shared -Wl,-soname,libfoo.so.major -o libfoo.so.major.minor
</PRE>
</CODE></BLOCKQUOTE>
<P>e tutto funzioner&agrave; alla perfezione.
<P>
<H3>a.out. Il formato tradizionale</H3>

<P>La facilit&agrave; con cui si esegue la compilazione di librerie condivise &egrave; uno 
dei motivi principali per passare a ELF.  Detto questo, &egrave; ancora possibile 
utilizzare a.out. Si prenda 
<A HREF="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz">ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz</A>
e si legga il documento di 20 pagine.
<P>
<H3><A NAME="index.76"></A> <A NAME="index.75"></A> ZMAGIC e QMAGIC  </H3>

<P>QMAGIC &egrave; un formato eseguibile proprio come i vecchi binari a.out 
(conosciuti anche come ZMAGIC), ma che lascia la prima pagina non mappata. 
Questo consente che accada pi&ugrave; facilmente un riferimento NULL dal momento 
che non esiste alcun mapping nel range 0-4096. Come effetto 
collaterale, i binari saranno di dimensioni inferiori (di circa 1 K).
<P>I linker obsoleti supportano solamente ZMAGIC, quelli semi-obsoleti 
supportano entrambi i formati, mentre le versioni attuali supportano solo 
QMAGIC. In realt&agrave; questo non ha importanza, dal momento che il kernel 
riesce ad eseguire entrambi i formati. 
<P>Il proprio comando 'file' dovrebbe essere in grado di identificare se un 
programma &egrave; QMAGIC.
<P>
<H3>Posizione dei file</H3>

<P>Una libreria condivisa a.out (DLL) &egrave; formata da due file reali e da 
un collegamento simbolico. Per la libreria '<CODE>foo</CODE>' utilizzata come 
esempio, questi file sarebbero <CODE>libfoo.sa</CODE> e <CODE>libfoo.so.1.2</CODE>;     
il collegamento simbolico sarebbe <CODE>libfoo.so.1</CODE> e punterebbe all'ultimo 
di questi file. Ma a cosa servono? 
<P>Durante la compilazione, ld ricerca <CODE>libfoo.sa</CODE>. Si tratta del
file 'matrice' della libreria, e contiene tutti i dati esportati e i 
puntatori alle funzioni richieste per il collegamento run time.
<P>Durante l'esecuzione, il loader dinamico cerca <CODE>libfoo.so.1</CODE>. Si 
tratta di un collegamento simbolico anzich&eacute; di un file reale in 
modo che le librerie possano essere aggiornate con versioni pi&ugrave; recenti e 
corrette senza procurare danni a nessuna delle applicazioni utilizzanti la 
libreria in quel momento. Dopo che la nuova versione, ad esempio 
<CODE>libfoo.so.1.3</CODE> - &egrave; stata introdotta, l'esecuzione di ldconfig
        commuter&agrave; il collegamento affinch&eacute; punti ad essa tramite un'operazione 
atomica, lasciando illeso ogni programma che stava utilizzando la vecchia 
versione.
<P>Le librerie DLL appaiono spesso pi&ugrave; grandi delle loro controparti 
statiche. Riservano spazio per future espansioni nella forma di 'buchi'         
che possono essere creati senza occupare spazio su disco. Una semplice 
chiamata <CODE>cp</CODE> o l'utilizzo del programma <CODE>makehole</CODE> raggiunger&agrave; 
questo scopo. Dopo la compilazione, &egrave; anche possibile rimuoverli, dal 
momento che gli indirizzi si trovano in locazioni fisse. Non tentare di 
rimuoverli dalle librerie ELF.
<P>
<H3>"libc-lite"?</H3>

<P>Un libc-lite &egrave; una versione ridotta della libreria libc per la quale &egrave; 
stata eseguita la compilazione in modo tale da stare su un floppy
disk ed essere sufficiente per tutti i task Unix essenziali. Non 
include codice <CODE>curse</CODE>, <CODE>dbm</CODE>, <CODE>termcap</CODE> ecc.  Se il proprio 
<CODE>/lib/libc.so.4</CODE> ha un collegamento con un lite lib, il 
sistema avvisa di sostituirlo con una versione completa.
<P>
<H3>Linking: problemi comuni</H3>

<P>Inviatemi i problemi derivanti dal linking! Anche se non potr&ograve; fare
niente per risolverli, ne scriver&ograve; un resoconto dettagliato.
<P>
<DL>
<DT><B>Programmi eseguono il link statico anzich&eacute; dinamico</B><DD><P>
<A NAME="index.77"></A>  
<A NAME="index.78"></A>  
<P>Controllare di avere i collegamenti corretti affinch&eacute; ld possa trovare 
tutte le librerie condivise. Per ELF questo significa un collegamento
simbolico <CODE>libfoo.so</CODE> per l'immagine, in a.out un file <CODE>libfoo.sa</CODE>. 
Molte persone hanno riscontrato questo problema dopo il passaggio dai 
binutils ELF 2.5 ai 2.6 - la versione precedente ricercava le librerie 
condivise in un modo 'pi&ugrave; intelligente' pertanto non avevano bisogno di 
creare tutti i collegamenti. Il comportamento intelligente &egrave; stato 
eliminato per compatibilit&agrave; con altre architetture, e perch&eacute; molto spesso 
le sue supposizioni erano sbagliate e causando pi&ugrave; guai di quanti fossero 
i problemi risolti.
<P>
<DT><B>Lo strumento DLL 'mkimage' non riesce a trovare libgcc</B><DD><P>
<A NAME="index.79"></A>  
<P>Da <CODE>libc.so.4.5.x</CODE> e oltre, <CODE>libgcc</CODE> non &egrave; pi&ugrave; condivisa. Pertanto, 
&egrave; necessario sostituire le occorrenze di '<CODE>-lgcc</CODE>'
con '<CODE>gcc -print-libgcc-file-name</CODE>'.
<P>Inoltre, bisogna cancellare tutti i file <CODE>/usr/lib/libgcc*</CODE>. Questo 
&egrave; molto importante.
<P>
<DT><B>Messaggi <CODE>__NEEDS_SHRLIB_libc_4 multiply defined</CODE></B><DD><P>Altra conseguenza del problema descritto al punto precedente.
<P>
<DT><B>Messaggio ``Assertion failure'' quando si ricompila una DLL?</B><DD><P>Questo messaggio criptico molto probabilmente significa che uno degli 
slot della propria jump table &egrave; andato in overflow poich&eacute; &egrave; 
stato riservato troppo poco spazio nel file jump.vars originale. &Egrave; 
possibile localizzare i colpevoli eseguendo il
comando '<CODE>getsize</CODE>' fornito nel pacchetto <CODE>tools-2.17.tar.gz</CODE>. Tuttavia, 
probabilmente l'unica soluzione consiste nel sostituire il numero di 
versione maggiore della libreria, forzandolo affinch&eacute; sia impossibile 
tornare indietro.
<P>
<DT><B><CODE>ld: output file needs shared library libc.so.4</CODE></B><DD><P>Questo accade solitamente quando si sta eseguendo il collegamento con 
librerie diverse da libc (come le librerie X), e si utilizza l'opzione 
<CODE>-g</CODE> sulla riga di link utilizzando anche <CODE>-static</CODE>.
<P>Gli stub <CODE>.sa</CODE> per le librerie condivise contengono solitamente 
un simbolo indefinito <CODE>_NEEDS_SHRLIB_libc_4</CODE> che viene risolto da 
<CODE>libc.sa</CODE>. Tuttavia, con <CODE>-g</CODE> si finisce di eseguire il 
collegamento con <CODE>libg.a</CODE> o <CODE>libc.a</CODE>, il simbolo non 
viene mai risolto, portando all'errore sopra descritto.
<P>In conclusione, aggiungere <CODE>-static</CODE> quando si compila con  
l'opzione <CODE>-g</CODE>, oppure non eseguire il collegamento con 
<CODE>-g</CODE>. Molto spesso &egrave; possibile ottenere informazioni di 
debugging sufficienti compilando i file individuali con 
<CODE>-g</CODE>, ed eseguendo il collegamento senza questa opzione.
<P>
</DL>
<P>
<H2><A NAME="ss6.5">6.5 Loading dinamico</A>
</H2>

<P>Questo paragrafo &egrave; per il momento piuttosto breve, verr&agrave; 
esteso in futuro.
<P>
<H3>Concetti</H3>

<P>Linux possiede delle librerie condivise, come si &egrave; visto diverse
molte volte nell'ultimo paragrafo.  Gran parte 
del lavoro di associazione dei nomi a locazioni, che 
tradizionalmente era svolto al momento del link, deve 
essere ritardato al momento del load (caricamento). 
<P>
<H3>Messaggi di errore</H3>

<P>I lettori sono pregati di inviare i proprii errori di link all'autore,
che anche se non potr&agrave; risolverli, comunque scriver&agrave; un 
resoconto dettagliato.
<P>
<DL>
<DT><B> <CODE>can't load library: /lib/libxxx.so, Incompatible version</CODE></B><DD><P>(solo in a.out) Questo significa che non si possiede la versione 
maggiore aggiornata della libreria xxx. Non &egrave; possibile semplicemente creare 
un collegamento simbolico ad un'altra versione che si possiede; nella migliore
delle ipotesi questo causer&agrave; un segfault nel proprio programma.  Si 
consiglia di ottenere una nuova versione. Una situazione 
simile in ELF produrr&agrave; un messaggio del tipo
<P>
<BLOCKQUOTE><CODE>
<PRE>
ftp: can't load library 'libreadline.so.2'
</PRE>
</CODE></BLOCKQUOTE>
<P>
<DT><B> <CODE>warning using incompatible library version xxx</CODE></B><DD><P>(solo in a.out) Si possiede una versione minore della libreria pi&ugrave; 
vecchia di quella posseduta dalla persona che ha 
compilato il programma in questione. Il programma 
funzioner&agrave; comunque. Tuttavia, un aggiornamento non sarebbe una cattiva 
idea.
<P>
</DL>
<P>
<H3><A NAME="index.81"></A> <A NAME="index.80"></A> Controllo delle operazioni del loader dinamico  </H3>

<P>Esistono diverse variabili di ambiente a che influenzano il comportamento del
loader dinamico. La maggior parte di esse sono pi&ugrave; utili a <CODE>ldd</CODE>
di quanto non lo siano per l'utente medio, e possono essere impostate 
eseguendo ldd con diverse opzioni. Includono
<P>
<UL>
<LI> <CODE>LD_BIND_NOW</CODE> --- normalmente, le funzioni non sono ricercate 
nelle librerie finch&eacute; non vengono chiamate. L'impostazione 
di questa opzione attiva la ricerca  all'atto del caricamento della libreria, 
determinando un tempo di avviamento maggiore. Pu&ograve; essere 
utile quando si vuole collaudare un programma per accertarsi che sia eseguito 
il link di tutte le parti.
</LI>
<LI> <CODE>LD_PRELOAD</CODE> --- pu&ograve; essere impostato con un file contenente delle 
definizioni di funzioni da sovrapporre. Ad esempio, se si sta eseguendo un 
test delle strategie di allocazione della memoria, e si vuole
sostituire 'malloc', &egrave; possibile scrivere la propria routine
sostitutiva, compilarla come <CODE>malloc.o</CODE> e utilizzare i comandi

<BLOCKQUOTE><CODE>
<PRE>
$ LD_PRELOAD=malloc.o; export LD_PRELOAD
$ programma_di_test
</PRE>
</CODE></BLOCKQUOTE>


<CODE>LD_ELF_PRELOAD</CODE> e <CODE>LD_AOUT_PRELOAD</CODE> sono simili, ma possono essere 
applicati solo al tipo binario appropriato. Se 
<CODE>LD_</CODE><B>qualcosa</B><CODE>_PRELOAD</CODE> e <CODE>LD_PRELOAD</CODE> sono entrambi impostati, 
verr&agrave; utilizzato quello pi&ugrave; specifico.
</LI>
<LI> <CODE>LD_LIBRARY_PATH</CODE> --- elenco, separato da virgole, di 
directory in cui ricercare le librerie condivise. <B>Non</B> ha effetti 
su ld, ma solo durante l'esecuzione. Inoltre, &egrave; disabilitato per programmi che 
eseguono setuid o setgid. <CODE>LD_ELF_LIBRARY_PATH</CODE> e <CODE>LD_AOUT_LIBRARY_PATH</CODE>
possono anche essere utilizzati per impostare la 
ricerca in modo differente per diversi tipi di binari. <CODE>LD_LIBRARY_PATH</CODE>
non dovrebbe essere necessario nelle operazioni normali; piuttosto aggiungere 
le directory a <CODE>/etc/ld.so.conf/</CODE> ed eseguire ldconfig.
</LI>
<LI> <CODE>LD_NOWARN</CODE> --- si applica solo ad a.out. Quando impostato (ossia 
con <CODE>LD_NOWARN=true; export LD_NOWARN</CODE>) evita che il <I>loader</I> fornisca i 
warning non fatali (come i messaggi per incompatibilit&agrave; di versione 
minore). 
</LI>
<LI> <CODE>LD_WARN</CODE> --- si applica solamente a ELF. Quando impostato, rende 
i messaggi, solitamente fatali, "Can't find library" dei semplici warning.
Non &egrave; molto utilizzato nelle operazioni normali, ma &egrave; importante per ldd. 
</LI>
<LI> <CODE>LD_TRACE_LOADED_OBJECTS</CODE> --- si applica solamente a ELF, e fa in 
modo che i programmi credano di essere in esecuzione sotto ldd:

<BLOCKQUOTE><CODE>
<PRE>
$ LD_TRACE_LOADED_OBJECTS=true /usr/bin/lynx
        libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
        libc.so.5 => /lib/libc.so.5.2.18
</PRE>
</CODE></BLOCKQUOTE>

</LI>
</UL>
<P>
<H3><A NAME="index.83"></A> <A NAME="index.82"></A> Scrivere programmi con il loading dinamico  </H3>

<P>Questo &egrave; molto simile al funzionamento del supporto di 
loading dinamico di Solaris 2.x. 
L'argomento &egrave; trattato ampiamente nel documento di 
programmazione ELF di H J Lu e nella pagina di manuale 
<CODE>dlopen(3) manual page</CODE>, che pu&ograve; essere trovata nel pacchetto 
ld.so. Segue un semplice esempio: &egrave; necessario effettuare il link con 
<CODE>-ldl</CODE>
<P>
<BLOCKQUOTE><CODE>
<PRE>
#include &lt;dlfcn.h>
#include &lt;stdio.h>

main()
{
    void *libc;
    void (*printf_call)();

    if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
    {
        printf_call=dlsym(libc,"printf");
        (*printf_call)("hello, world\n");
    }

}
</PRE>
</CODE></BLOCKQUOTE>
<P>
<HR>
<A HREF="GCC-HOWTO-7.html">Avanti</A>
<A HREF="GCC-HOWTO-5.html">Indietro</A>
<A HREF="GCC-HOWTO.html#toc6">Indice</A>
</BODY>
</HTML>