GCC HOWTO pour Linux
par Daniel Barlow <
[email protected]>
v1.17, 28 fevrier 1996
(Adaptation francaise par Eric Dumas <
[email protected]>, 8 Avril
1996). Ce document presente la maniere de configurer le compilateur
GNU C et les bibliotheques de developpement sous Linux. Il donne un
apercu de la compilation, de l'edition de liens, de l'execution et du
debogage de programmes sous Linux. Bon nombre de passages de ce docu-
ment sont empruntes a la FAQ GCC redigee par Mitch D'Souza's et au
HowTo ELF. Ceci est la premiere version publique (en depit du numero
de version : en fait, ca vient de RCS). N'hesitez pas a me joindre
pour toute remarque.
11.. PPrreelliimmiinnaaiirreess
11..11..
EELLFF eett aa..oouutt
Le developpement de Linux est actuellement dans une phase de
transition. En resume, il existe deux formats de binaires que Linux
reconnait et execute, et cela depend de la maniere dont votre systeme
est configure : vous pouvez avoir les deux, l'un ou l'autre. En lisant
ce document, vous pourrez savoir quels binaires votre systeme est
capable de gerer.
Comment le savoir ? Utilisez la commande file (par exemple, file
/bin/bash). Pour un programme ELF, cette commande va vous repondre
quelque chose dans lequel se trouve le mot ELF. Dans le cas d'un
programme en a.out, il vous indiquera quelque chose comme Linux/i386.
Les differences entre ELF et a.out sont detaillees plus tard dans ce
document. ELF est le nouveau format et il est considere comme etant
meilleur.
11..22..
DDuu ccoottee dduu ccooppyyrriigghhtt
Le copyright et autres informations legales peuvent etre trouves a la
_f_i_n de ce document, avec les avertissements conventionnels concernant
la maniere de poser des questions sur Usenet pour eviter d'avoir a
reveler votre ignorance du langage C en annoncant des bogues qui n'en
sont pas, etc.
11..33.. TTyyppooggrraapphhiiee
Si vous lisez ce document au format Postscript, dvi, ou HTML, vous
pouvez voir quelques difference entre les styles d'ecriture alors que
les gens qui consultent ce document au format texte pur ne verront
aucune difference. En particulier, les noms de fichiers, le nom des
commandes, les messages donnes par les programmes et les codes sources
seront ecrits avec le style suivant : style d'ecriture, alors que les
noms de variables entre autres choses seront en _i_t_a_l_i_q_u_e.
Vous aurez egalement un index. Avec les formats dvi ou postscript, les
chiffres dans l'index correspondent au numeros de paragraphes. Au
format HTML, il s'agit d'une numerotation sequentielle pour que vous
puissiez cliquer dessus. Avec le format texte, ce ne sont que des
nombres. Il vous est donc conseille de prendre un autre format que le
format texte !
L'interpreteur de commande (_s_h_e_l_l) utilise dans les exemples sera la
Bourne shell (plutot que le C-Shell). Les utilisateurs du C-Shell
utiliseront plutot :
% setenv soif JD
la ou j'ai ecrit
$ soif=JD; export soif
Si l'invite (_p_r_o_m_p_t dans la langue de Shakespeare) est # plutot que
$, la commande ne fonctionnera que si elle est executee au nom de
Root. Bien sur, je decline toute responsabilite de ce qui peut se
produire sur votre systeme lors de l'execution de ces exemples. Bonne
chance :-)
22.. OOuu rreeccuuppeerreerr ddee llaa ddooccuummeennttaattiioonn eett lleess pprrooggrraammmmeess ??
22..11.. CCee ddooccuummeenntt
Ce document fait partie de la serie des HOWTO pour Linux, et il est
donc disponible ainsi que ces collegues dans les repertoires HowTo
pour Linux, comme sur <
http://sunsite.unc.edu/pub/linux/docs/HOWTO/>.
La version HTML peut egalement etre consultee sur
<
http://ftp.linux.org.uk/~barlow/howto/gcc-howto.html>.
Note du traducteur : vous pouvez obtenir tous les HowTos en langue
anglaise et francaise sur ftp.ibp.fr:/pub/linux. Les versions
francaises se trouvent dans le repertoire /pub/linux/french/HOWTO.
22..22..
AAuuttrreess ddooccuummeennttaattiioonn
La documentation officielle pour gcc se trouve dans les sources de la
distribution (voir plus bas) sous la forme de fichiers texinfo et de
fichiers .info. Si vous possedez une connexion rapide, un CD-ROM ou
une certaine patience, vous pouvez desarchiver la documentation et
l'installer dans le repertoire /usr/info. Sinon, vous pouvez toujours
les trouver sur tsx-11
<
ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/>, mais ce n'est pas
necessairement toujours la derniere version.
Il existe deux sources de documentation pour la libc. La libc GNU est
fournie avec des fichiers info qui decrivent assez precisement la libc
Linux sauf pour la partie des entrees-sorties. Vous pouvez egalement
trouver sur sunsite <
ftp://sunsite.unc.edu/pub/Linux/docs/> des
documents ecrits pour Linux ainsi que la description de certaines
appels systemes (section 2) et certaines fonctions de la libc (section
3).
Note du traducteur : un bemol concernant cette partie... La libc Linux
n'est pas GNU et tend a etre relativement differente sur certains
points.
22..33.. GGCCCC
Il existe deux types de reponses
(a) La distribution officielle de GCC pour Linux peut toujours etre
recuperee sous la forme de binaires (deja compilee) sur
<
ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/>. Vous pouvez la
trouver sur le miroir francais
<
ftp://ftp.ibp.fr:/pub/linux/packages/GCC/>. A l'heure ou j'ecris ces
lignes, la derniere version est gcc 2.7.2 (gcc-2.7.2.bin.tar.gz).
(b) La derniere distribution des sources de GCC de la _F_r_e_e _S_o_f_t_w_a_r_e
_F_o_u_n_d_a_t_i_o_n peut-etre recuperee sur prep.ai.mit.edu
<
ftp://prep.ai.mit.edu/pub/gnu/> ou ftp.ibp.fr
<
ftp://ftp.ibp.fr/pub/gnu/>. Ce n'est pas toujours la meme version
que celle presentee ci-dessus. Les mainteneurs de GCC pour Linux ont
rendu la compilation de GCC plus facile grace a l'utilisation du
script configure qui effectue la configuration d'une maniere
automatique. Regardez dans tsx-11
<
ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/> ou ftp.ibp.fr
<
ftp://ftp.ibp.fr:/pub/linux/packages/GCC/> pour recuperer d'eventuels
patches.
Quelle que soit la complexite de votre programme, vous aurez egalement
besoin de la _l_i_b_c.
22..44..
LLeess ffiicchhiieerrss dd''eenn--tteettee eett llaa bbiibblliiootthheeqquuee CC
Ce que vous allez trouver dans ce paragraphe depend
+o de votre systeme (ELF ou a.out) ;
+o du type de binaire que vous desirez generer.
Si vous etes en train de mettre a jour votre libc 4 en libc 5, vous
devriez consulter le ELF HowTo qui se trouve au meme endroit que ce
document.
Les libc sont disponibles sur tsx-11
<
ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/> ou ftp.ibp.fr
<
ftp://ftp.ibp.fr:/pub/linux/packages/GCC/>. Voici une description des
fichiers situes dans ce repertoire :
lliibbcc--55..22..1188..bbiinn..ttaarr..ggzz
--- bibliotheques dynamiques et statiques ELF plus les fichiers
d'en-tete pour la bibliotheque C et la bibliotheque
mathematique.
lliibbcc--55..22..1188..ttaarr..ggzz
--- Code source pour la bibliotheque ci-dessus. Vous aurez
egalement besoin du paquetage .bin. pour avoir les fichiers
d'en-tete. Si vous hesitez entre compiler la bibliotheque C
vous-meme et utiliser les binaires, la bonne reponse est dans la
majorite des cas est d'utiliser les binaires. Toutefois, si vous
desirer utiliser NYS (NdT : NYS != NIS) ou bien les mots de
passe _s_h_a_d_o_w, vous devrez recompiler la libc par vous-meme.
lliibbcc--44..77..55..bbiinn..ttaarr..ggzz
--- bibliotheques dynamiques et statiques a.out pour la version
4.7.5 de la libc. Cette bibliotheque a ete concue pour pouvoir
coexister avec le paquetage de la libc 5 decrit ci-dessus, mais
c'est uniquement necessaire si vous desirez utiliser ou
developper des programmes au format a.out.
22..55..
OOuuttiillss aassssoocciieess ((aass,, lldd,, aarr,, ssttrriinnggss,, eettcc..))
Ces outils se trouvent comme les bibliotheques dans le repertoire
tsx-11 <
ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/>, et ftp.ibp.fr
<
ftp://ftp.ibp.fr:/pub/linux/packages/GCC/>. La version actuelle est
binutils-2.6.0.2.bin.tar.gz.
Il est utile de remarquer que ces outils ne sont disponibles qu'au
format ELF, que la libc actuelle est ELF et que la libc a.out ne pose
pas de probleme lorsqu'elle est utilisee avec la libc ELF. Le
developpement de la libc est relativement rapide et a moins que n'ayez
de bonnes raisons pour utiliser le format a.out, vous etes encourages
a suivre le mouvement.
33.. IInnssttaallllaattiioonn eett ccoonnffiigguurraattiioonn ddee GGCCCC
33..11..
LLeess vveerrssiioonnss ddee GGCCCC
Vous pouvez savoir quelle est la version de GCC que vous possedez en
tapant gcc -v lors de l'invite. C'est egalement une bonne technique
pour savoir si votre configuration est ELF ou a.out. Sur mon systeme,
cela donne ceci :
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-zorglub-linux/2.7.2/specs
gcc version 2.7.2
Les mots-clefs a remarquer
+o i486. Cela vous indique que la version de gcc que vous utilisez a
ete compilee pour etre utilisee sur un processeur 486 --- mais vous
pouvez avoir un autre processeur comme un 386 ou un Pentium (586).
Tous ces processeurs peuvent executer le code compile avec
n'importe quel processeur. La seule difference reside dans le fait
que le code 486 rajoute un peu de code a certains endroits pour
aller plus vite sur un 486. Cela n'a pas d'effet nefaste cote
performance sur un 386 mais cela rend les executables un peu plus
importants.
+o zorglub. Ce n'est pas reellement important, et il s'agit
generalement d'un commentaire (comme slackware or debian) ou meme,
cela peut-etre vide (lorsque vous avez comme nom de repertoire
i486-linux). Si vous construisez votre propre gcc, vous pouvez
fixer ce parametre selon vos desirs, comme je l'ai fait. :-)
+o linux. Cela peut etre a la place linuxelf ou linuxaout et en fait,
la signification varie en fonction de la version que vous possedez.
+o linux signifie ELF si la version est 2.7.0 ou superieure, sinon,
c'est du a.out.
+o linuxaout signifie a.out. Cela a ete introduit comme cible lorsque
le format des binaires a change de a.out vers ELF dans LLiinnuuxx.
Normalement, vous ne verrez plus de linuxaout avec une version de
gcc superieure a 2.7.0.
+o linuxelf est depasse. Il s'agit generalement de gcc version 2.6.3
configure pour generer des executables ELF. Notez que gcc 2.6.3 est
connu pour generer de nombreuses erreurs lorsqu'il produit du code
ELF --- une mise a jour est tres fortement recommandee.
+o 2.7.2 est le numero de la version de GCC.
Donc, en resume, nous possedons gcc 2.7.2 qui genere du code ELF.
_Q_u_e_l_l_e _s_u_r_p_r_i_s_e (NdT: En francais dans le texte) !
33..22.. AA qquueell eennddrrooiitt ss''iinnssttaallllee GGCCCC ??
Si vous avez installe gcc sans regarder, ou bien si vous l'avez eu a
partir d'une distribution, vous pouvez avoir envie de savoir ou il se
trouve dans votre arborescence. Les mots clefs permettant cela sont
+o /usr/lib/gcc-lib/_m_a_c_h_i_n_e_-_c_i_b_l_e/_v_e_r_s_i_o_n/ (et ses sous-repertoires)
est generalement l'endroit ou se trouve le plus souvent le
compilateur. Ceci inclut les executables qui realisent la
compilation ainsi que certaines bibliotheques et quelques fichiers
d'en-tete.
+o /usr/bin/gcc est le lanceur du compilateur --- c'est en fait le
programme que vous lancez. Il peut etre utilise avec plusieurs
versions de gcc lorsque vous possedez plusieurs repertoires
installes (voir plus bas). Pour trouver la version par defaut
utilisee, lancez gcc -v. Pour forcer l'utilisation d'une autre
version, lancez gcc -V _v_e_r_s_i_o_n. Par exemple,
# gcc -v
Reading specs from /usr/lib/gcc-lib/i486-zorglub-linux/2.7.2/specs
gcc version 2.7.2
# gcc -V 2.6.3 -v
Reading specs from /usr/lib/gcc-lib/i486-zorglub-linux/2.6.3/specs
gcc driver version 2.7.2 executing gcc version 2.6.3
+o /usr/_m_a_c_h_i_n_e_-_c_i_b_l_e/(bin|lib|include)/. Si vous avez installe
plusieurs cibles possibles (par exemple a.out et elf, ou bien un
compilateur croise, les bibliotheques, les binutils (as, ld, etc.)
et les fichiers d'en-tete pour les cibles differente de celle par
defaut peuvent etre trouves a cet endroit. Meme si vous n'avez
qu'une seule version de gcc installee, vous devriez toutefois
trouver a cet endroit un certain nombre de fichiers. Si ce n'est
pas la cas, regardez dans /usr/(bin|lib|include).
+o /lib/, /usr/lib et autres sont les repertoires pour les
bibliotheques pour le systeme initial. Vous aurez egalement besoin
du programme /lib/cpp pour un grand nombre d'applications (X
l'utilise beaucoup) --- soit vous le copiez a partir de
/usr/lib/gcc-lib/_m_a_c_h_i_n_e_-_c_i_b_l_e/_v_e_r_s_i_o_n/, soit vous faites pointer
un lien symbolique dessus.
33..33..
OOuu ssee ttrroouuvveenntt lleess ffiicchhiieerrss dd''eenn--tteettee ??
Si l'on excepte les fichier fichiers d'en-tete que vous installez dans
le repertoire /usr/local/include, il y a en fait trois types de
fichiers d'en-tete :
+o La grande majorite des fichiers situes dans le repertoire
/usr/include/ et dans ses sous-repertoires proviennent du paquetage
de la libc dont s'occupe H.J. Lu. Je dis bien la "grande majorite"
car vous pouvez avoir egalement certains fichiers provenant
d'autres sources (par exemple des bibliotheques curses et dbm),
ceci est d'autant plus vrai si vous possedez une distribution de la
libc recente (ou les bibliotheques curses et dbm ne sont pas
integrees).
+o Les repertoires /usr/include/linux et /usr/include/asm (pour les
fichiers <linux/*.h> et <asm/*.h>) doivent etre des liens
symboliques vers les repertoires linux/include/linux et
linux/include/asm situes dans les sources du noyau. Vous devrez
installer ces sources si vous desirez pouvoir developper : ces
sources ne sont pas utilises uniquement pour compiler le noyau.
Il est probable que vous ayez besoin de lancer la commande suivante
make config dans le repertoire des sources du noyau apres les avoir
installes. Beaucoup de fichiers ont besoin du fichier d'en-tete
<linux/autoconf.h> qui n'existe pas sans cette commande. Il est a
noter que dans certaines versions du noyau, le repertoire asm est
en fait un lien symbolique qui n'est cree qu'avec l'execution de
make config.
Donc, si vous installez les sources du noyau dans le repertoire
/usr/src/linux, il suffit de faire :
$ cd /usr/src/linux
$ su
# make config
[repondez aux questions. A moins que vous ne recompiliez votre
noyau, les reponses importent peu]
# cd /usr/include
# ln -s ../src/linux/include/linux .
# ln -s ../src/linux/include/asm .
+o Les fichiers tels que <float.h>, <limits.h>, <varargs.h>,
<stdarg.h> et <stddef.h> changent en fonction de la version du
compilateur, et peuvent etre trouves dans le repertoire
/usr/lib/gcc-lib/i486-box-linux/2.7.2/include/ pour la version
2.7.2.
33..44.. CCoonnssttrruuiirree uunn ccoommppiillaatteeuurr ccrrooiissee
33..44..11.. LLiinnuuxx ccoommmmee ppllaattee--ffoorrmmee ddee ddeessttiinnaattiioonn
Nous supposons que vous avez recupere les sources de gcc, et
normalement, il vous suffit de suivre les instructions donnees dans le
fichier INSTALL situe dans les sources de gcc. Ensuite, il suffit de
lancer configure --target=i486-linux --host=XXX sur une plateforme
XXX, puit un make devrait compiler gcc correctement. Il est a noter
que vous aurez besoin des fichiers d'en-tete de Linux, ainsi que les
sources de l'assembleur et du l'editeur de liens croises que vous
pouvez trouver sur <
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/> ou
<
ftp://ftp.ibp.fr/pub/linux/GCC/>.
33..44..22.. LLiinnuuxx ccoommmmee ppllaattee--ffoorrmmee oorriiggiinnee eett MMSSDDOOSS ccoommmmee ddeessttiinnaattiioonn
Arggg. Apparemment, cela est possible en utilisant le paquetage " emx
" ou l'extension " go ". Regardez
<
ftp://sunsite.unc.edu/pub/Linux/devel/msdos> pour plus
d'informations.
Je n'ai pas teste cela et je ne pense pas le faire !
44.. PPoorrttaaggee eett ccoommppiillaattiioonn
44..11..
SSyymmbboolleess ddeeffiinniiss aauuttoommaattiiqquueemmeenntt
Vous pouvez trouver quels symboles votre version de gcc definit
automatiquement en le lancant avec l'option -v. Par exemple cela
donne ca chez moi :
$ echo 'main(){printf("Bonjour !\n");}' | gcc -E -v -
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
/usr/lib/gcc-lib/i486-box-linux/2.7.2/cpp -lang-c -v -undef
-D__GNUC__=2 -D__GNUC_MINOR__=7 -D__ELF__ -Dunix -Di386 -Dlinux
-D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386
-D__linux -Asystem(unix) -Asystem(posix) -Acpu(i386)
-Amachine(i386) -D__i486__ -
Si vous ecrivez du code qui utilise des specificites Linux, il est
souhaitable d'implementer le code non portable de la maniere suivante
#ifdef __linux__
/* ... code linux ... */
#endif /* linux */
Utilisez __linux__ pour cela, et _p_a_s linux. Bien que cette macro soit
definie, ce n'est pas une specification POSIX.
44..22.. OOppttiioonnss ddee ccoommppiillaattiioonn
La documentation des options de compilation se trouve dans les pages
_i_n_f_o de gcc (sous Emacs, utilisez C-h i puis selectionnez l'option
`gcc'). Votre distribution peut ne pas avoir installe la
documentation ou bien vous pouvez en avoir une ancienne. Dans ce cas,
la meilleure chose a faire est de recuperer les sources de gcc depuis
<
ftp://prep.ai.mit.edu/pub/gnu> ou l'un des ses nombreux miroirs dont
<
ftp://ftp.ibp.fr/pub/gnu>.
La page de manuel gcc (gcc.1) est en principe, completement depassee.
Cela vous met en garde si vous desirez la consulter.
44..22..11..
OOppttiioonnss ddee ccoommppiillaattiioonn
gcc peut realiser un certain nombre d'optimisations sur le code genere
en ajoutant l'option -O_n a la ligne de commandes, ou _n est un chiffre.
La valeur de _n, et son effet exact, depend de la version de gcc, mais
s'echelonne normalement entre 0 (aucune optimisation) et 2 (un certain
nombre) ou 3 (toutes les optimisations possibles).
En interne, gcc interprete les options telles que -f et -m. Vous
pouvez voir exactement ce qu'effectue le niveau specifie dans l'option
-O en lancant gcc avec l'option -v et l'option (non documentee) -Q.
Par exemple, l'option -O2, effectue les operations suivantes sur ma
machine :
enabled: -fdefer-pop -fcse-follow-jumps -fcse-skip-blocks
-fexpensive-optimizations
-fthread-jumps -fpeephole -fforce-mem -ffunction-cse -finline
-fcaller-saves -fpcc-struct-return -frerun-cse-after-loop
-fcommon -fgnu-linker -m80387 -mhard-float -mno-soft-float
-mno-386 -m486 -mieee-fp -mfp-ret-in-387
Utiliser un niveau d'optimisation superieur a celui que le compilateur
supporte (par exemple -O6) aura le meme effet qu'utiliser le plus haut
niveau gere. Distribuer du code ou la compilation est configuree de
cette maniere est une tres mauvaise idee -- si d'autres optimisations
sont incorporees dans de versions futures, vous (ou d'autres
utilisateurs) pouvez vous apercevoir que cela ne compile plus, ou bien
que le code genere ne fait pas les actions desirees.
Les utilisateurs de gcc 2.7.0 a 2.7.2 devraient noter qu'il y a un
bogue dans l'option -O2. Plus precisement, la _s_t_r_e_n_g_t_h _r_e_d_u_c_t_i_o_n ne
fonctionne pas. Un patch a ete implemente pour resoudre ce probleme,
mais vous devez alors recompiler gcc. Sinon, vous devrez toujours
compiler avec l'option -fno-strength-reduce.
44..22..11..11.. SSppeecciiffiiccaattiioonn dduu pprroocceesssseeuurr
Il existe d'autres options -m qui ne sont pas positionnees lors de
l'utilisation de -O mais qui sont neanmoins utiles dans certains cas.
C'est le cas pour les options -m386 et -m486, qui indiquent a gcc de
generer un code plus ou moins optimise pour l'un ou l'autre type de
processeur. Le code continuera a fonctionner sur les deux processeurs.
Bien que le code pour 486 soit plus important, il ne ralentit pas
l'execution du programme sur 386.
Il n'existe pas actuellement de -mpentium ou -m586. Linus a suggere
l'utilisation des options -m486 -malign-loops=2 -malign-jumps=2
-malign-functions=2, pour exploiter les optimisations du 486 tout en
perdant de la place due aux problemes d'alignements (dont le Pentium
n'a que faire). Michael Meissner (de Cygnus) nous dit :
" Mon avis est que l'option -mno-strength-reduce permet
d'obtenir un code plus rapide sur un x86 (nota : je ne parle
pas du bogue _s_t_r_e_n_g_t_h _r_e_d_u_c_t_i_o_n, qui est un autre probleme).
Cela s'explique en raison du peu de registres dont disposent
ces processeurs (et la methode de GCC qui consiste a grouper
les registres dans l'ordre inverse au lieu d'utiliser
d'autres registres n'arrange rien). La _s_t_r_e_n_g_t_h _r_e_d_u_c_t_i_o_n
consiste en fait a rajouter des registres pour remplacer les
multiplications par des additions. Je suspecte egalement
-fcaller-saves de ne pas arranger la situation. "
Une autre idee est que -fomit-frame-pointer n'est pas obli-
gatoirement une bonne idee. D'un cote, cela peut signifier
qu'un autre registre est disponible pour une allocation.
D'un autre cote, vue la maniere dont les processeurs x86
codent leur jeu d'instruction, cela peut signifier que la
pile des adresses relatives prend plus de place que les
adresses de fenetres relatives, ce qui signifie en clair que
moins de cache est disponible pour l'execution du processus.
Il faut preciser que l'option -fomit-frame-pointer, signifie
que le compilateur doit constamment ajuster le pointeur de
pile apres les appels, alors qu'avec une fenetre, il peut
laisser plusieurs appels dans la pile.
Le mot final sur le sujet provient de Linus :
Remarquez que si vous voulez des performances maximales, ne
me croyez pas : testez ! Il existe tellement d'options de
gcc, et il est possible que cela ne soit une reelle optimi-
sation que pour vous.
44..22..22..
IInntteerrnnaall ccoommppiilleerr eerrrroorr:: cccc11 ggoott ffaattaall ssiiggnnaall 1111
Signal 11 correspond au signal SIGSEGV, ou bien _s_e_g_m_e_n_t_a_t_i_o_n
_v_i_o_l_a_t_i_o_n. Normalement, cela signifie que le programme s'est melange
les pointeurs et a essaye d'ecrire la ou il n'en a pas le droit. Donc,
cela pourrait etre un bug de gcc.
Toutefois, gcc est un logiciel assez teste et assez remarquable de ce
cote. Il utilise un grand nombre de structures de donnees complexes,
et un nombre impressionnant de pointeurs. En resume, c'est le plus
pointilleux des testeurs de memoire existants. Si vous _n_'_a_r_r_i_v_e_z _p_a_s _a
_r_e_p_r_o_d_u_i_r_e _l_e _b_o_g_u_e --- si cela ne s'arrete pas au meme endroit
lorsque vous retentez la compilation --- c'est plutot un probleme avec
votre machine (processeur, memoire, carte mere ou bien cache).
NN''aannnnoonncceezz ppaass la decouverte d'un nouveau bogue si votre ordinateur
traverse tous les tests du BIOS, ou s'il fonctionne correctement sous
Windows ou autre : ces tests ne valent rien. Il en va de meme si le
noyau s'arrete lors du `make zImage' ! `make zImage' doit compiler
plus de 200 fichiers, et il en faut bien moins pour arriver a faire
echouer une compilation.
Si vous arrivez a reproduire le bogue et (mieux encore) a ecrire un
petit programme qui permet de mettre en evidence cette erreur, alors
vous pouvez envoyer le code soit a la FSF, soit dans la liste linux-
gcc. Consultez la documentation de gcc pour plus de details
concernant les informations necessaires.
44..33.. PPoorrttaabbiilliittee
Cette phrase a ete dite un jour : si quelque chose n'a pas ete porte
vers Linux alors ce n'est pas important de l'avoir :-).
Plus serieusement, en general seules quelques modifications mineures
sont necessaires car Linux repond a 100% aux specifications POSIX. Il
est generalement sympathique d'envoyer a l'auteur du programme les
modifications effectuees pour que le programme fonctionne sur Linux,
pour que lors d'une future version, un `make' suffise pour generer
l'executable.
44..33..11.. <<ssggttttyy..hh>>) Specificites BSD (notamment bsd_ioctl, daemon et
Vous pouvez compiler votre programme avec l'option -I/usr/include/bsd
et faire l'edition de liens avec -lbsd (en ajoutant -I/usr/include/bsd
a la ligne CFLAGS et -lbsd a la ligne LDFLAGS dans votre fichier
Makefile). Il est egalement necessaire de ne ppaass ajouter
-D__USE_BSD_SIGNAL si vous voulez que les signaux BSD fonctionnent car
vous les avez inclus automatiquement avec la ligne -I/usr/include/bsd
et en incluant le fichier d'en-tete <signal.h>.
44..33..22..
SSiiggnnaauuxx _m_a_n_q_u_a_n_t_s ((SSIIGGBBUUSS, SIGEMT, SIGIOT, SIGTRAP, SIGSYS, etc.)
Linux respecte les specifications POSIX. Ces signaux n'en font pas
partie (cf. ISO/IEC 9945-1:1990 - IEEE Std 1003.1-1990, paragraphe
B.3.3.1.1) :
" Les signaux SIGBUS, SIGEMT, SIGIOT, SIGTRAP, et SIGSYS ont
ete omis de la norme POSIX.1 car leur comportement est
dependant de l'implementation et donc ne peut etre reperto-
rie d'une maniere satisfaisante. Certaines implementations
peuvent fournir ces signaux mais doivent documenter leur
effet "
La maniere la plus elegante de regler ce probleme est de redefinir ces
signaux a SIGUNUSED. La maniere _n_o_r_m_a_l_e de proceder est d'entourer le
code avec les #ifdef appropries :
#ifdef SIGSYS
/* ... code utilisant les signaux non posix .... */
#endif
44..33..33..
CCooddee KK && RR
GCC est un compilateur ANSI, or il existe beaucoup de code qui ne soit
pas ANSI.
Il n'y a pas grand chose a faire, sauf rajouter l'option -traditional
lors de la compilation. Il effectue certaines verifications
supplementaires. Consultez les pages info gcc.
Notez que l'option -traditional a pour unique effet de changer la
forme du langage accepte par gcc. Par exemple, elle active l'option
-fwritable-strings, qui deplace toutes les chaines de caracteres vers
l'espace de donnees (depuis l'espace de texte, ou elle ne peuvent pas
etre modifiees). Ceci augmente la taille de la memoire occupee par le
programme.
44..33..44.. lleess pprroottoottyyppeess dduu ccooddee
LLeess ssyymmbboolleess dduu pprreepprroocceesssseeuurr pprroodduuiisseenntt uunn ccoonnfflliitt aavveecc
Un des problemes frequents se produit lorsque certaines fonctions
standards sont definies comme macros dans les fichiers d'en-tete de
Linux et le preprocesseur refusera de traiter des prototypes
identiques. Par exemple, cela peut arriver avec atoi() et atol().
44..33..55..
sspprriinnttff(())
Parfois, soyez prudent lorsque vous effectuez un portage a partir des
sources de programmes fonctionnant sous SunOs, surtout avec la
fonction sprintf(string, fmt, ...) car elle renvoie un pointeur sur la
chaine de caracteres alors que Linux (suivant la norme ANSI) retourne
le nombre de caracteres recopies dans la chaine de caracteres.
44..33..66..
ffccnnttll et ses copains. Ou se trouve la definition de FD_* et compagnie
?
Dans <sys/time.h>. Si vous utilisez fcntl vous voudrez probablement
inclure <unistd.h> egalement, pour avoir le prototype de la fonction.
D'une maniere generale, la page de manuel pour une fonction donne la
liste des fichiers d'en-tete a inclure.
44..33..77.. ccoommmmeenncceenntt ddaannss uunn eettaatt dd''aatttteennttee aaccttiivvee
LLee ttiimmeeoouutt ddee sseelleecctt(()). Les programmes
A une certaine epoque, le parametre timeout de la fonction select()
etait utilise en lecture seule. C'est pourquoi la page de manuel
comporte une mise en garde :
select() devrait retourner normalement le temps ecoule
depuis le timeout initial, s'il s'est declenche, en modifi-
ant la valeur pointee par le parametre time. Cela sera peut-
etre implemente dans les versions ulterieures du systeme.
Donc, il n'est pas vraiment prudent de supposer que les don-
nees pointees ne seront pas modifiees lors de l'appel a
select().
Mais tout arrive avec le temps ! Lors d'un retour de select(),
l'argument timeout recevra le temps ecoule depuis la derniere
reception de donnees. Si aucune donnee n'est arrivee, la valeur sera
nulle, et les futurs appels a cette fonction utilisant le meme timeout
auront pour resultat un retour immediat.
Pour resoudre le probleme, il suffit de mettre la valeur timeout dans
la structure a chaque appel de select(). Le code initial etait
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
while (some_condition)
select(n,readfds,writefds,exceptfds,&timeout);
et doit devenir :
struct timeval timeout;
while (some_condition)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
select(n,readfds,writefds,exceptfds,&timeout);
}
Certaines versions de Mosaic etaient connues a une certaine epoque
pour avoir ce probleme.
La vitesse de rotation du globe terrestre etait inversement
proportionnelle a la vitesse de transfert des donnees !
44..33..88..
AAppppeellss ssyysstteemmeess iinntteerrrroommppuuss
44..33..88..11.. SSyymmppttoommeess ::
Lorsqu'un processus est arrete avec un Ctrl-Z et relance - ou bien
lorsqu'un autre signal est declenche dans une situation differente :
par exemple avec un Ctrl-C, la terminaison d'un processus, etc, on dit
qu'il y a " interruption d'un appel systeme " , ou bien " write :
erreur inconnue " ou des trucs de ce genre.
44..33..88..22.. PPrroobblleemmeess ::
Les systemes POSIX verifient les signaux plus souvent que d'autres
Unix plus anciens. Linux peux lancer les gestionnaires de signaux :
+o d'une maniere asynchrone (sur un top d'horloge)
+o lors d'un retour de n'importe quel appel systeme
+o pendant l'execution des appels systemes suivants : select(),
pause(), connect(), accept(), read() sur des terminaux, des
sockets, des pipes ou des fichiers situes dans /proc, write() sur
des terminaux, des sockets, des pipes ou des imprimantes, open()
sur des FIFOs, des lignes PTYs ou series, ioctl() sur des
terminaux, fcntl() avec la commande F_SETLKW, wait4(), syslog(), et
toute operation d'ordre TCP ou NFS.
Sur d'autres systemes d'exploitation, il est possible que vous ayez a
inclure dans cette categorie les appels systemes suivants : creat(),
close(), getmsg(), putmsg(), msgrcv(), msgsnd(), recv(), send(),
wait(), waitpid(), wait3(), tcdrain(), sigpause(), semop().
Si un signal (que le programme desire traiter) est lance pendant
l'execution d'un appel systeme, le gestionnaire est lance. Lorsque le
gestionnaire du signal se termine, l'appel systeme detecte qu'il a ete
interrompu et se termine avec la valeur -1 et errno = EINTR. Le
programme n'est pas forcement au courant de ce qui s'est passe et donc
s'arrete.
Vous pouvez choisir deux solutions pour resoudre ce probleme.
(1)Dans tout gestionnaire de signaux que vous mettez en place, ajoutez
l'option SA_RESTART au niveau de _s_i_g_a_c_t_i_o_n. Par exemple, modifiez
signal (signal_id, mon_gestionnaire_de_signaux);
en
signal (signal_id, mon_gestionnaire_de_signaux);
{
struct sigaction sa;
sigaction (signal_id, (struct sigaction *)0, &sa);
#ifdef SA_RESTART
sa.sa_flags |= SA_RESTART;
#endif
#ifdef SA_INTERRUPT
sa.sa_flags &= ~ SA_INTERRUPT;
#endif
sigaction (signal_id, &sa, (struct sigaction *)0);
}
Notez que lors de certains appels systemes vous devrez souvent
regarder si errno n'a pas ete positionnee a EINTR par vous meme comme
avec read(), write(), ioctl(), select(), pause() et connect().
(2) A la recherche de EINTR :
Voici deux exemples avec read() et ioctl(),
Voici le code original utilisant read()
int result;
while (len > 0)
{
result = read(fd,buffer,len);
if (result < 0)
break;
buffer += result;
len -= result;
}
et le nouveau code
int result;
while (len > 0)
{
result = read(fd,buffer,len);
if (result < 0)
{
if (errno != EINTR)
break;
}
else
{
buffer += result;
len -= result;
}
}
Voici un code utilisant ioctl()
int result;
result = ioctl(fd,cmd,addr);
et cela devient
int result;
do
{
result = ioctl(fd,cmd,addr);
}
while ((result == -1) && (errno == EINTR));
Il faut remarquer que dans certaines versions d'Unix de type BSD on a
l'habitude de relancer l'appel systeme. Pour recuperer les
interruptions d'appels systemes, vous devez utiliser les options
SV_INTERRUPT ou SA_INTERRUPT.
44..33..99.. "" sseeggmmeennttaattiioonn ffaauulltt "" dd''uunnee mmaanniieerree aalleeaattooiirree))
LLeess cchhaaiinneess eett lleeuurrss aacccceess eenn eeccrriittuurreess ((oouu lleess pprrooggrraammmmeess qquuii pprroovvoo--
qquueenntt ddeess
GCC a une vue optimiste en ce qui concerne ses utilisateurs, en
croyant qu'ils respectent le fait qu'une chaine dite constante l'est
reellement. Donc, il les range dans la zone _t_e_x_t_e_(_c_o_d_e_) du programme,
ou elles peuvent etre chargees puis dechargees a partir de l'image
binaire de l'executable situee sur disque (ce qui evite d'occuper de
l'espace disque). Donc, toute tentative d'ecriture dans cette chaine
provoque un " segmentation fault ".
Cela peut poser certains problemes avec d'anciens codes, par exemple
ceux qui utilisent la fonction mktemp() avec une chaine constante
comme argument. mktemp() essaye d'ecrire dans la chaine passee en
argument.
Pour resoudre ce probleme,
1. compilez avec l'option -fwritable-strings pour indiquer a gcc de
mettre les chaines constantes dans l'espace de donnees
2. reecrire les differentes parties du code pour allouer une chaine
non constante puis effectuer un strcpy des donnees dedans avant
d'effectuer l'appel.
44..33..1100..
PPoouurrqquuooii ll''aappppeell aa eexxeeccll(()) echoue ?
Tout simplement parce que vous l'utilisez mal. Le premier argument
d'execl est le programme que vous desirez executer. Le second et ainsi
de suite sont en fait le elements du tableau argv que vous appelez.
Souvenez-vous que argv[0] est traditionnellement fixe meme si un
programme est lance sans argument. Vous devriez donc ecrire :
execl("/bin/ls","ls",NULL);
et pas
execl("/bin/ls", NULL);
Lancer le programme sans argument est considere comme etant une
demande d'affichage des bibliotheques dynamiques associees au
programme, si vous utilisez le format a.out. ELF fonctionne d'une
maniere differente.
(Si vous desirez ces informations, il existe des outils plus simples;
consultez la section sur le chargement dynamique, ou la page de manuel
de ldd).
55.. DDeebboogguueerr eett ooppttiimmiisseerr
55..11..
EEttuuddee pprreevveennttiivvee dduu ccooddee ((lliinntt))
Il n'existe pas de lint qui soit reellement utilisable, tout
simplement parce que la grande majorite des developpeurs sont
satisfaits des messages d'avertissement de gcc. Il est probable que
l'option la plus utile est l'option -Wall --- qui a pour effet
d'afficher tous les avertissements possibles.
Il existe une version du domaine public du programme lint que vous
pouvez trouver a l'adresse suivante :
<
ftp://larch.lcs.mit.edu/pub/Larch/lclint>. Je ne sais pas ce qu'elle
vaut.
55..22..
DDeebboogguueerr
55..22..11..
CCoommmmeenntt rreennddrree ddeebbooggaabbllee uunn pprrooggrraammmmee ??
Vous devez compiler et effectuer l'edition de liens avec l'option -g,
et sans l'option -fomit-frame-pointer. En fait, vous ne devez
compiler que les modules que vous avez besoin de deboguer.
Si vous possedez un systeme a.out, les bibliotheques dynamiques sont
compilees avec l'option -fomit-frame-pointer, que gcc ne peut pas
gerer. Lorsque vous compilez avec l'option -g, alors par defaut vous
effectuez une edition de liens statique, ce qui permet de resoudre le
probleme.
Si l'editeur de liens echoue avec un message disant qu'il n'arrive pas
a trouver la bibliotheque libg.a, c'est que vous ne possedez pas la
bibliotheque /usr/lib/libg.a, qui est la bibliotheque C standard
permettant le debogage. Cette bibliotheque est fournie dans le
paquetage des binaires de la libc., ou (dans les nouvelles versions)
vous aurez besoin de recuperer le source et de le compiler vous-meme.
Vous n'avez pas reellement besoin de cela en fait, vous pouvez faire
un lien logique vers /usr/lib/libc.a
55..22..11..11..
CCoommmmeenntt rreedduuiirree llaa ttaaiillllee ddeess eexxeeccuuttaabblleess ??
Bon nombre de produits GNU sont fournis pour compiler avec l'option
-g, ce qui genere des executables d'une taille tres importante (et
souvent l'edition de liens s'effectue d'une maniere statique). Ce
n'est pas une idee lumineuse...
Si le programme possede le script configure genere par autoconf, vous
pouvez modifier les options de debogage en effectuant un vous pouvez
aller modifier le Makefile. Bien sur, si vous utilisez le format ELF,
l'edition de liens sera effectuee de maniere dynamique meme avec
l'option -g. Dans ce cas, vous pouvez effectuer un strip sur
l'executable.
55..22..22..
PPrrooggrraammmmeess ddiissppoonniibblleess
Beaucoup de gens utilisent ggddbb, que vous pouvez recuperer sur le site
prep.ai.mit.edu <
ftp://prep.ai.mit.edu/pub/gnu>, sous une forme
binaire sur tsx-11 <
ftp://tsx-11.mit.edu/pub/linux/packages/GCC> ou
sur sunsite. xxxxggddbb est une surcouche X de gdb (c.a.d. que vous avez
besoin de gdb pour utiliser xxgdb). Les sources peuvent etre recuperes
sur <
ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz>
Il existe egalement le debogueur UUPPSS qui a ete porte par Rick Sladkey.
Il fonctionne sous X egalement, mais a la difference d'xxgdb, ce n'est
qu'une surcouche X pour un debogueur en mode en texte. Il possede
certaines caracteristiques tres interessantes et si vous utilisez
beaucoup ce genre d'outils, vous l'essayerez surement. Les patches
ainsi que des versions precompilees pour Linux peuvent etre trouvees
sur <
ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/>, et les sources
peuvent etre recuperes sur
<
ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z>.
Un autre outil que vous pouvez trouver utile pour deboguer est "
ssttrraaccee " , qui affiche les appels systemes que le processus lance. Il
possede d'autres caracteristiques telles que donner les chemins
d'acces ou ont ete compiles les binaires, donner les temps passes dans
chacun des appels systemes, et il vous permet egalement de connaitre
les resultats des appels. La derniere version de strace (actuellement
la version 3.0.8) peut etre trouvee sur <
ftp://ftp.std.com/pub/jrs/>.
55..22..33.. PPrrooggrraammmmeess eenn ttaacchhee ddee ffoonndd ((ddeemmoonn))
Les demons lancent typiquement un fork() des leur lancement et
terminent donc le pere. Cela fait une session de deboguage tres
courte.
La maniere la plus simple de resoudre ce probleme est de poser un
point d'arret sur fork, et lorsque le programme s'arrete, forcer le
retour a 0.
(gdb) list
1 #include <stdio.h>
2
3 main()
4 {
5 if(fork()==0) printf("child\n");
6 else printf("parent\n");
7 }
(gdb) break fork
Breakpoint 1 at 0x80003b8
(gdb) run
Starting program: /home/dan/src/hello/./fork
Breakpoint 1 at 0x400177c4
Breakpoint 1, 0x400177c4 in fork ()
(gdb) return 0
Make selected stack frame return now? (y or n) y
#0 0x80004a8 in main ()
at fork.c:5
5 if(fork()==0) printf("child\n");
(gdb) next
Single stepping until exit from function fork,
which has no line number information.
child
7 }
55..22..44.. FFiicchhiieerrss ccoorree
Lorsque Linux se lance, il n'est generalement pas configure pour
produire des fichiers core. Si vous les voulez vous devez utiliser
votre shell pour ca en faisant sous csh (ou tcsh) :
% limit core unlimited
avec sh, bash, zsh, pdksh, utilisez
$ ulimit -c unlimited
Si vous voulez pousser le vice a nommer votre fichier core (par
exemple si vous utilisez un debogueur bogue... ce qui est un comble)
vous pouvez simplement modifier le noyau. Editez les fichiers
fs/binfmt_aout.c et fs/binfmt_elf.c (dans les nouveaux noyaux, vous
devrez chercher ailleurs) :
memcpy(corefile,"core.",5);
#if 0
memcpy(corefile+5,current->comm,sizeof(current->comm));
#else
corefile[4] = '\0';
#endif
et changez les 0 par des 1.
55..33.. CCaarraacctteerriissttiiqquueess dduu pprrooggrraammmmee
Il est possible d'examiner un peu le programme pour savoir quels sont
les appels de fonctions qui sont effectues le plus souvent ou bien qui
prennent du temps. C'est une bonne maniere d'optimiser le code en
determinant la ou l'on passe le plus de temps. Vous devez compiler
tous les objets avec l'option -p, et pour mettre en forme la sortie
ecran, vous aurez besoin du programme gprof (situe dans les binutils).
Consultez les pages de manuel gprof pour plus de details.
66.. EEddiittiioonn ddee lliieennss
Entre les deux formats de binaires incompatibles, bibliotheques
statiques et dynamiques, on peut comparer l'operation d'edition de
lien en fait a un jeu ou l'on se demanderait qu'est-ce qui se passe
lorsque je lance le programme ? Cette section n'est pas vraiment
simple...
Pour dissiper la confusion qui regne, nous allons nous baser sur ce
qui se passe lors d'execution d'un programme, avec le chargement
dynamique. Vous verrez egalement la description de l'edition de liens
dynamiques, mais plus tard. Cette section est dediee a l'edition de
liens qui intervient a la fin de la compilation.
66..11.. BBiibblliiootthheeqquueess ppaarrttaaggeeeess ccoonnttrree bbiibblliiootthheeqquueess ssttaattiiqquueess
La derniere phase de construction d'un programme est de realiser
l'edition de liens, ce qui consiste a assembler tous les morceaux du
programme et de chercher ceux qui sont manquants. Bien evidement,
beaucoup de programmes realisent les memes operations comme ouvrir des
fichiers par exemple, et ces pieces qui realisent ce genre
d'operations sont fournies sous la forme de bibliotheques. Sous Linux,
ces bibliotheques peuvent etre trouvees dans les repertoires /lib
et/usr/lib/ entre autres.
Lorsque vous utilisez une bibliotheque statique, l'editeur de liens
cherche le code dont votre programme a besoin et en effectue une copie
dans le programme physique genere. Pour les bibliotheques partagees,
c'est le contraire : l'editeur de liens laisse du code qui lors du
lancement du programme chargera automatiquement la bibliotheque. Il
est evident que ces bibliotheques permettent d'obtenir un executable
plus petit; elles permettent egalement d'utiliser moins de memoire et
moins de place disque. Linux effectue par defaut une edition de liens
dynamique s'il peut trouver les bibliotheques de ce type sinon, il
effectue une edition de liens statique. Si vous obtenez des binaires
statiques alors que vous les voulez dynamiques verifiez que les
bibliotheques existent (*.sa pour le format a.out, et *.so pour le
format ELF) et que vous possedez les droits suffisants pour y acceder
(lecture).
Sous Linux, les bibliotheques statiques ont pour nom libnom.a, alors
que les bibliotheques dynamiques sont appelees libnnom.so.x.y.z ou
x.y.z represente le numero de version. Les bibliotheques dynamiques
ont souvent des liens logiques qui pointent dessus, et qui sont tres
importants. Normalement, les bibliotheques standards sont livrees sous
la double forme dynamique et statique.
Vous pouvez savoir de quelles bibliotheques dynamiques un programme a
besoin en utilisant la commande ldd (_L_i_s_t _D_y_n_a_m_i_c _D_e_p_e_n_d_e_n_c_i_e_s)
$ ldd /usr/bin/lynx
libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
libc.so.5 => /lib/libc.so.5.2.18
Cela indique sur mon systeme que l'outil lynx (outil WWW) a besoin des
bibliotheques dynamiques libc.so.5 (la bibliotheque C) et de
libncurses.so.1 (necessaire pour le controle du terminal). Si un
programme ne possede pas de dependances, ldd indiquera `_s_t_a_t_i_c_a_l_l_y
_l_i_n_k_e_d' (edition de liens statique).
66..22..
AA llaa rreecchheerrcchhee ddeess ffoonnccttiioonnss...... oouu ddaannss qquueellllee bbiibblliiootthheeqquuee ssee ttrroouuvvee
llaa ffoonnccttiioonn ssiinn(()) ?')
nm _n_o_m_d_e_b_i_b_l_i_o_t_h_e_q_u_e vous donne tous les symboles references dans la
bibliotheque. Cela fonctionne que cela soit du code statique ou
dynamique. Supposez que vous vouliez savoir ou se trouve definie la
fonction tcgetattr() :
$ nm libncurses.so.1 |grep tcget
U tcgetattr
La lettre U vous indique que c'est indefini (_U_n_d_e_f_i_n_e_d) --- cela
indique que la bibliotheque ncurses l'utilise mais ne la definit pas.
Vous pouvez egalement faire :
$ nm libc.so.5 | grep tcget
00010fe8 T __tcgetattr
00010fe8 W tcgetattr
00068718 T tcgetpgrp
La lettre `W' indique que le symbole est defini mais de telle maniere
qu'il peut etre surcharge par une autre definition de la fonction dans
une autre bibliotheque (W pour _w_e_a_k : faible). Une definition normale
est marquee par la lettre `T' (comme pour tcgetpgrp).
La reponse a la question situee dans le titre est libm.(so|a). Toutes
les fonctions definies dans le fichier d'en-tete <math.h> sont
implementees dans la bibliotheque mathematique donc vous devrez
effectuer l'edition de liens grace a -lm.
66..33.. TTrroouuvveerr lleess ffiicchhiieerrss
Supposons que vous ayez le message d'erreur suivant de la part de
l'editeur de liens :
ld: Output file requires shared library `libfoo.so.1`
La strategie de recherche de fichiers de ld ou de ses copains differe
de la version utilisee, mais vous pouvez etre sur que les fichiers
situes dans le repertoire /usr/lib seront trouves. Si vous desirez que
des fichiers situes a un endroit different soient trouves, il est
preferable d'ajouter l'option -L a gcc ou ld.
Si cela ne vous aide pas clairement, verifiez que vous avez le bon
fichier a l'endroit specifie. Pour un systeme a.out, effectuer
l'edition de liens avec -ltruc implique que ld recherche les
bibliotheques libtruc.sa (bibliotheques partagees), et si elle
n'existe pas, il recherche libtruc.a (statique). Pour le format ELF,
il cherche libtruc.so puis libtruc.a. libtruc.so est generalement un
lien symbolique vers libtruc.so.x.
66..44.. CCoommppiilleerr vvoottrree pprroopprree bbiibblliiootthheeqquuee
66..44..11.. NNuummeerroo ddee llaa vveerrssiioonn
Comme tout programme, les bibliotheques ont tendance a avoir quelques
bogues qui sont corriges au fur et a mesure. De nouvelles
fonctionnalites sont ajoutees et qui peuvent changer l'effet de celles
qui existent ou bien certaines anciennes peuvent etres supprimees.
Cela peut etre un probleme pour les programmes qui les utilisent.
Donc, nous introduisons la notion de numero de version. Nous
repertorions les modifications effectuees dans la bibliotheques comme
etant soit mineures soit majeures. Cela signifie qu'une modification
mineure ne peut pas modifier le fonctionnement d'un programme (en
bref, il continue a fonctionner comme avant). Vous pouvez identifier
le numero de la version de la bibliotheque en regardant son nom (en
fait c'est un mensonge pour les bibliotheques ELF... mais continuez a
faire comme si !) : libtruc.so.1.2 a pour version majeure 1 et mineure
2. Le numero de version mineur peut etre plus ou moins eleve --- la
bibliotheque C met un numero de patch, ce qui produit un nom tel que
libc.so.5.2.18, et c'est egalement courant d'y trouver des lettres ou
des blancs soulignes ou tout autre caractere ASCII affichable.
Une des principales differences entre les formats ELF et a.out se
trouve dans la maniere de construire la bibliotheque partagee. Nous
traiterons les bibliotheques partagees en premier car c'est plus
simple.
66..44..22..
EELLFF,, qquu''eesstt--ccee qquuee cc''eesstt ??
ELF (_E_x_e_c_u_t_a_b_l_e _a_n_d _L_i_n_k_i_n_g _F_o_r_m_a_t) est format de binaire initialement
concu et developpe par USL (_U_N_I_X _S_y_s_t_e_m _L_a_b_o_r_a_t_o_r_i_e_s) et utilise dans
les systemes Solaris et System R4. En raison de sa facilite
d'utilisation par rapport a l'ancien format dit a.out qu'utilisait
Linux, les developpeurs de GCC et de la bibliotheque C ont decide
l'annee derniere de basculer tout le systeme sous le format ELF. ELF
est desormais le format binaire standard sous Linux.
66..44..22..11.. EELLFF,, llee rreettoouurr !!
Ce paragraphe provient du groupe '/news-archives/comp.sys.sun.misc'.
ELF (_E_x_e_c_u_t_a_b_l_e _L_i_n_k_i_n_g _F_o_r_m_a_t) est le " nouveau et plus
performant " format de fichier introduit dans SVR4. ELF est
beaucoup plus puissant que le sacro-saint format COFF, dans
le sens ou il est extensible. ELF voit un fichier objet
comme une longue liste de sections (plutot qu'un tableau de
taille fixe d'elements). Ces sections, a la difference de
COFF ne se trouvent pas a un endroit constant et ne sont pas
dans un ordre particulier, etc. Les utilisateurs peuvent
ajouter une nouvelle section a ces fichiers objets s'il
desirent y mettre de nouvelles donnees. ELS possede un for-
mat de debogage plus puissant appele DWARF (_D_e_b_u_g_g_i_n_g _W_i_t_h
_A_t_t_r_i_b_u_t_e _R_e_c_o_r_d _F_o_r_m_a_t) - par encore entierement gere par
Linux (mais on y travaille !). Une liste chainee de " DWARF
DIEs " (ou _D_e_b_u_g_g_i_n_g _I_n_f_o_r_m_a_t_i_o_n _E_n_t_r_i_e_s - NdT... le lecteur
aura surement note le jeu de mot assez noir : dwarf = nain;
dies = morts) forment la section _._d_e_b_u_g dans ELF. Au lieu
d'avoir une liste de petits enregistrements d'information
de taille fixes, les DWARF DIEs contiennent chacun une
longue liste complexe d'attributs et sont ecrits sous la
forme d'un arbre de donnees. Les DIEs peuvent contenir une
plus grande quantite d'information que la section _._d_e_b_u_g du
format COFF ne le pouvait (un peu comme les graphes d'her-
itages du C++).
Les fichiers ELF sont accessibles grace a la bibliotheque
d'acces de SVR4 (Solaris 2.0 peut-etre ?), qui fournit une
interface simple et rapide aux parties les plus complexes
d'ELF. Une des aubaines que permet la bibliotheque d'acces
ELF est que vous n'avez jamais besoin de connaitre les mean-
dres du format ELF. Pour acceder a un fichier Unix, on
utilise un Elf *, retourne par un appel a elf_open().
Ensuite, vous effectuez des appels a elf_foobar() pour
obtenir les differents composants au lieu d'avoir a triturer
le fichier physique sur le disque (chose que beaucoup
d'utilisateurs de COFF ont fait...).
Les arguments pour ou contre ELF, et les problemes lies a la mise a
jour d'un systeme a.out vers un systeme ELF sont decrits dans le ELF-
HOWTO et je ne veux pas effectuer de copier coller ici (NdT: ce HowTo
est egalement traduit en francais). Ce HowTo se trouve au meme
endroit que les autres.
66..44..22..22.. LLeess bbiibblliiootthheeqquuee ppaarrttaaggeeeess EELLFF
Pour construire libtruc.so comme une bibliotheque dynamique, il suffit
de suivre les etapes suivantes :
$ gcc -fPIC -c *.c
$ gcc -shared -Wl,-soname,libtruc.so.1 -o libtruc.so.1.0 *.o
$ ln -s libtruc.so.1.0 libtruc.so.1
$ ln -s libtruc.so.1 libtruc.so
$ LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ; export LD_LIBRARY_PATH
Cela va generer une bibliotheque partagee appelee libtruc.so.1.0, les
liens appropries pour ld (libtruc.so) et le chargeur dynamique
(libtruc.so.1) pour le trouver. Pour tester, nous ajoutons le
repertoire actuel a la variable d'environnement LD_LIBRARY_PATH.
Lorsque vous etes satisfait et que la bibliotheque fonctionne, vous
n'avez plus qu'a la deplacer dans le repertoire par exemple,
/usr/local/lib, et de recreer les liens appropries. Le lien de
libtruc.so.1 sur libtruc.so.1.0 est enregistre par ldconfig, qui sur
bon nombre de systemes est lance lors du processus d'amorcage. Le lien
libfoo.so doit etre mis a jour a la main. Si vous faites attention
lors de la mise a jour de la bibliotheque la chose la plus simple a
realiser est de creer le lien libfoo.so -> libfoo.so.1, pour que
ldconfig conserve les liens actuels. Si vous ne faites pas cela, vous
aurez des problemes plus tard. Ne me dites pas que l'on ne vous a pas
prevenu !
$ /bin/su
# cp libtruc.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libtruc.so.1 libtruc.so )
66..44..22..33..
LLeess nnuummeerrooss ddee vveerrssiioonn,, lleess nnoommss eett lleess lliieennss
Chaque bibliotheque possede un nom propre (_s_o_n_a_m_e). Lorsque l'editeur
de liens en trouve un qui correspond a un nom cherche, il enregistre
le nom de la bibliotheque dans le code binaire au lieu d'y mettre le
nom du fichier de la bibliotheque. Lors de l'execution, le chargeur
dynamique va alors chercher un fichier ayant pour nom le nom propre de
la bibliotheque, et pas le nom du fichier de la bibliotheque. Par
exemple, une bibliotheque ayant pour nom libtruc.so peut avoir comme
nom propre libbar.so, et tous les programmes lies avec vont alors
chercher libbar.so lors de leur execution.
Cela semble etre une nuance un peu pointilleuse mais c'est la clef de
la comprehension de la coexistence de plusieurs versions differentes
de la meme bibliotheque sur le meme systeme. On a pour habitude sous
Linux d'appeler une bibliotheque libtruc.so.1.2 par exemple, et de lui
donner comme nom propre libtruc.so.1. Si cette bibliotheque est
rajoutee dans un repertoire standard (par exemple dans /usr/lib), le
programme ldconfig va creer un lien symbolique entre libtruc.so.1 ->
libtruc.so.1.2 pour que l'image appropriee soit trouvee lors de
l'execution. Vous aurez egalement besoin d'un lien symbolique
libtruc.so -> libtruc.so.1 pour que ld trouve le nom propre lors de
l'edition de liens.
Donc, lorsque vous corrigez des erreurs dans la bibliotheque ou bien
lorsque vous ajoutez de nouvelles fonctions (en fait, pour toute
modification qui n'affecte pas l'execution des programmes deja
existants), vous reconstruisez la bibliotheque, conservez le nom
propre tel qu'il etait et changez le nom du fichier. Lorsque vous
effectuez des modifications que peuvent modifier le deroulement des
programmes existants, vous pouvez tout simplement incrementer le
nombre situe dans le nom propre --- dans ce cas, appelez la nouvelle
version de la bibliotheque libtruc.so.2.0, et donnez-lui comme nom
propre libtruc.so.2. Maintenant, faites pointer le lien de libfoo.so
vers la nouvelle version et tout est bien dans le meilleur des mondes
!
Il est utile de remarquer que vous n'etes pas oblige de nommer les
bibliotheques de cette maniere, mais c'est une bonne convention. Elf
vous donne une certaine liberte pour nommer des bibliotheques tant et
si bien que cela peut perturber certains utilisateurs, mais cela ne
veut pas dire que vous etes oblige de le faire.
Resume : supposons que choisissiez d'adopter la methode traditionnelle
avec les mises a jour majeures qui peuvent ne pas etre compatibles
avec les versions precedentes et les mises a jour mineures qui ne
posent pas ce probleme. Il suffit de creer la bibliotheque de cette
maniere :
gcc -shared -Wl,-soname,libtruc.so.majeur -o libtruc.so.majeur.mineur
et tout devrait etre parfait !
66..44..33.. aa..oouutt.. LLee bboonn vviieeuuxx ffoorrmmaatt
La facilite de construire des bibliotheque partagees est la raison
principale de passer a ELF. Ceci dit, il est toujours possible de
creer des bibliotheques dynamiques au format a.out. Recuperez le
fichier archive
<
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz> et
lisez les 20 pages de documentation que vous trouverez dedans apres
l'avoir desarchive. Je n'aime pas avoir l'air d'etre aussi partisan,
mais il est clair que je n'ai jamais aime ce format :-).
66..44..33..11..
ZZMMAAGGIICC ccoonnttrree QQMMAAGGIICC
QMAGIC est le format des executables qui ressemble un peu aux vieux
binaires a.out (egalement connu comme ZMAGIC), mais qui laisse la
premiere page libre. Cela permet plus facilement de recuperer les
adresses non affectees (comme NULL) dans l'intervalle 0-4096 (NdT :
Linux utilise des pages de 4Ko).
Les editeurs de liens desuets ne gerent que le format ZMAGIC, ceux un
peu moins rustiques gerent les deux, et les plus recents uniquement le
QMAGIC. Cela importe peu car le noyau gere les deux types.
La commande file est capable d'identifier si un programme est de type
QMAGIC.
66..44..33..22.. GGeessttiioonn ddeess ffiicchhiieerrss
Une bibliotheque dynamique a.out (DLL) est composee de deux fichiers
et d'un lien symbolique. Supposons que l'on utilise la bibliotheque
_t_r_u_c, les fichiers seraient les suivants : libtruc.sa et
libtruc.so.1.2; et le lien symbolique aurait pour nom libtruc.so.1 et
pointerait sur le dernier des fichiers. Mais a quoi servent-ils ?
Lors de la compilation, ld cherche libtruc.sa. C'est le fichier de
description de la bibliotheque : il contient toutes les donnees
exportees et les pointeurs vers les fonctions necessaires pour
l'edition de liens.
Lors de l'execution, le chargeur dynamique cherche libtruc.so.1.
C'est un lien symbolique plutot qu'un reel fichier pour que les
bibliotheques puissent etre mise a jour sans avoir a casser les
applications qui utilisent la bibliotheque. Apres la mise a jour,
disons que l'on est passe a la version libfoo.so.1.3, le lancement de
ldconfig va positionner le lien. Comme cette operation est atomique,
aucune application fonctionnant n'aura de probleme.
Les bibliotheques DLL (Je sais que c'est une tautologie... mais pardon
!) semblent etre tres souvent plus importantes que leur equivalent
statique. En fait, c'est qu'elles reservent de la place pour les
extensions ulterieures sous la simple forme de trous qui sont fait de
telle maniere qu'ils n'occupent pas de place disque (NdT : un peu
comme les fichiers core). Toutefois, un simple appel a cp ou a
makehole les remplira... Vous pouvez effectuer une operation de strip
apres la construction de la bibliotheque, comme les adresses sont a
des endroits fixes. NNee ffaaiitteess ppaass llaa mmeemmee ooppeerraattiioonn aavveecc lleess
bbiibblliiootthheeqquueess EELLFF !!
66..44..33..33.. "" lliibbcc--lliittee "" ??
Une " libc-lite " (contraction de _l_i_b_c et _l_i_t_t_l_e) est une version
epuree et reduite de la bibliotheque libc construite de telle maniere
qu'elle puisse tenir sur une disquette avec un certain nombre d'outil
Unix. Elle n'inclut pas curses, dbm, termcap, ... Si votre
/lib/libc.so.4 est liee avec une bibliotheque de ce genre il est tres
fortement conseille de la remplacer avec une version complete.
66..44..44.. EEddiittiioonn ddee lliieennss :: pprroobblleemmee ccoouurraannttss
Envoyez-les moi !
DDeess pprrooggrraammmmeess ssttaattiiqquueess lloorrssqquuee vvoouuss lleess vvoouulleezz
partages"
Verifiez que vous avez les bons liens pour que ld puisse trouver
les bibliotheques partagees. Pour ELF cela veut dire que
libtruc.so est un lien symbolique sur son image, pour a.out un
fichier libtruc.sa. Beaucoup de personnes ont eu ce probleme
apres etre passes des outils ELF 2.5 a 2.6 (binutils) --- la
derniere version effectue une recherche plus intelligente pour
les bibliotheques dynamiques et donc ils n'avaient pas cree tous
les liens symboliques necessaires. Cette caracteristique avait
ete supprimee pour des raisons de compatibilite avec d'autres
architectures et parce qu'assez souvent cela ne marchait pas
bien. En bref, cela posait plus de problemes qu'autre chose.
LLee pprrooggrraammmmee ``mmkkiimmaaggee'' nn''aarrrriivvee ppaass aa ttrroouuvveerr lliibbggcccc
Comme libc.so.4.5.x et suivantes, libgcc n'est pas une
bibliotheque partagee. Vous devez remplacer les `-lgcc' sur la
ligne de commande par `gcc -print-libgcc-file-name` (entre
quotes)
Egalement, detruisez tous les fichiers situes dans
/usr/lib/libgcc*. C'est important.
LLee mmeessssaaggee ____NNEEEEDDSS__SSHHRRLLIIBB__lliibbcc__44 mmuullttiippllyy ddeeffiinneedd
Sont une consequence du meme probleme.
LLee mmeessssaaggee ````AAsssseerrttiioonn ffaaiilluurree'''' aappppaarraaiitt lloorrssqquuee vvoouuss
rreeccoonnssttrruuiisseezz uunnee
DLL" Ce message enigmatique signifie qu'un element de votre
table _j_u_m_p a depasse la table car trop peu de place etait
reservee dans le fichier jump.vars file. Vous pouvez trouver
le(s) coupable(s) en lancant la commande getsize fournie dans le
paquetage tools-2.17.tar.gz. La seule solution est de passer a
une nouvelle version majeure, meme si elle sera incompatible
avec les precedentes.
lldd:: oouuttppuutt ffiillee nneeeeddss sshhaarreedd lliibbrraarryy lliibbcc..ssoo..44
Cela arrive lorsque vous effectuez l'edition de liens avec des
bibliotheques differentes de la libc (comme les bibliotheques X)
et que vous utilisez l'option -g sans utiliser l'option -static.
Les fichiers .sa pour les bibliotheques dynamiques ont un
symbole non resolu _NEEDS_SHRLIB_libc_4 qui est defini dans
libc.sa. Or, lorsque vous utilisez -g vous faites l'edition de
liens avec libg.a ou libc.a et donc ce symbole n'est jamais
defini.
Donc, pour resoudre le probleme, ajoutez l'option -static
lorsque vous compilez avec l'option -g, ou n'utilisez pas -g
lors de l'edition de liens !
77.. CChhaarrggeemmeenntt ddyynnaammiiqquuee
_C_e _p_a_r_a_g_r_a_p_h_e _e_s_t _e_n _f_a_i_t _u_n _p_e_u _c_o_u_r_t _: _i_l _s_e_r_a _e_t_e_n_d_u _d_a_n_s _u_n_e
_v_e_r_s_i_o_n _u_l_t_e_r_i_e_u_r_e _d_e_s _q_u_e _j_'_a_u_r_a_i _r_e_c_u_p_e_r_e _l_e _H_o_w_T_o _E_L_F
77..11.. CCoonncceeppttss
Linux possede des bibliotheques dynamiques, comme on vous le repete
depuis le debut de ce document ! Or, il existe un systeme pour
reporter le travail d'association des noms des symboles et de leur
adresse dans la bibliotheque, qui est normalement effectue lors de
l'edition de liens en l'effectuant lors du chargement du programme.
77..22.. MMeessssaaggeess dd''eerrrreeuurr
Envoyez moi vos erreurs ! Je n'en fait pas grand chose sauf les
inserer dans ce paragraphe...
ccaann''tt llooaadd lliibbrraarryy:: //lliibb//lliibbxxxxxx..ssoo,, IInnccoommppaattiibbllee vveerrssiioonn
(seulement a.out) Cela signifie que vous n'avez pas la version
correcte de la bibliotheque (numero dit majeur). Non, il n'est
pas possible d'effectuer un lien symbolique sur la bibliotheque
que vous possedez : si vous avez de la chance, vous obtiendrez
un _s_e_g_m_e_n_t_a_t_i_o_n _f_a_u_l_t. Recuperez la nouvelle version. Un
message un peu equivalent existe egalement sur les systemes ELF
:
ftp: can't load library 'libreadline.so.2'
wwaarrnniinngg uussiinngg iinnccoommppaattiibbllee lliibbrraarryy vveerrssiioonn xxxxxx
(seulement a.out) Vous avez un numero de version de bibliotheque
(mineur) inferieur a la version avec laquelle a ete compile le
programme. Le programme fonctionnera surement. Une mise a jour
est toutefois conseillee.
77..33..
CCoonnttrroolleerr ll''ooppeerraattiioonn ddee cchhaarrggeemmeenntt ddyynnaammiiqquuee
Il existe certaines variables d'environnements que le chargeur
dynamique utilise. Beaucoup sont exploitees par le programme ldd
lorsqu'il s'agit de particularites de l'environnement de
l'utilisateur, ce qui peuvent etre positionnees pour lancer ldd avec
des options particulieres. Voici une description des differentes
variables d'environnement que vous pouvez rencontrer :
+o LD_BIND_NOW --- normalement, les fonctions ne sont pas cherchees
dans les bibliotheques avant leur appel. En positionnant cette
option, vous verifiez que toutes les fonctions employees dans votre
programmes se trouvent bien dans la bibliotheque lors de son
chargement, ce qui ralentit le lancement du programme. C'est utile
lorsque vous voulez tester que l'edition de liens s'est
parfaitement deroulee et que tous les symboles sont bien associes.
+o LD_PRELOAD peut etre defini avec un nom de fichier qui contient des
fonctions surchargeant des fonctions deja existantes. Par exemple,
si vous testez une strategie d'allocation memoire, et que vous
voulez remplacer le malloc de la bibliotheque C par le votre situe
dans un module ayant pour nom malloc.o, il vous suffit de faire :
$ export LD_PRELOAD=malloc.o
$ test_mon_malloc
LD_ELF_PRELOAD et LD_AOUT_PRELOAD sont similaires, mais leur utilisa-
tion est specifique au type de binaire utilise. Si LD__T_y_p_e_B_i_-
_n_a_i_r_e_PRELOAD et LD_PRELOAD sont positionnes, celui correspondant le
mieux a la machine est utilise.
+o LD_LIBRARY_PATH contient une liste de repertoires contenant les
bibliotheques dynamiques. Cela n'affecte pas l'edition de liens :
cela n'a qu'un effet lors de l'execution. Il faut noter qu'elle est
desactivee pour des programmes qui s'executent avec un setuid ou un
setgid. Enfin, LD_ELF_LIBRARY_PATH et LD_AOUT_LIBRARY_PATH peuvent
etre utilises pour orienter le mode de compilation du binaire.
LD_LIBRARY_PATH ne devrait pas etre necessaire en principe :
ajoutez les repertoires dans le fichier /etc/ld.so.conf/ et
relancez ldconfig.
+o LD_NOWARN s'applique au format a.out uniquement. Lorsqu'elle est
positionnee (c.a.d si elle existe par exemple avec LD_NOWARN=true;
export LD_NOWARN) cela arrete le chargeur du programme meme sur des
avertissements insignifiants (tels que des messages
d'incompatibilites de numeros mineurs de version).
+o LD_WARN s'applique a ELF uniquement. Lorsqu'elle est positionnee,
on transforme le message habituellement fatal _C_a_n_'_t _f_i_n_d _l_i_b_r_a_r_y en
un avertissement. Ce n'est pas positionne par defaut mais c'est
important pour un programme comme ldd.
+o LD_TRACE_LOADED_OBJECTS s'applique a ELF uniquement, et permet de
simuler l'execution des programmes comme s'ils l'etaient par ldd :
$ 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
77..44..
EEccrriirree ddeess pprrooggrraammmmeess eenn uuttiilliissaanntt llee cchhaarrggeemmeenntt ddyynnaammiiqquuee
Cela ressemble enormement au systeme de chargement dynamique utilise
sous Solaris 2.x. Ce systeme est decrit d'une maniere precise dans le
document expliquant la programmation avec ELF ecrit par H J Lu et dans
la page de manuel dlopen(3), qui se trouve dans le paquetage ld.so.
Voici un exemple simple : pensez a faire l'edition de liens avec -ldl
#include <dlfcn.h>
#include <stdio.h>
main()
{
void *libc;
void (*printf_call)();
if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
{
printf_call = dlsym(libc,"printf");
(*printf_call)("Bonjour ! Ha ben ca marche pil poil sous Linux !\n");
}
}
88.. CCoonnttaacctteerr lleess ddeevveellooppppeeuurrss
88..11..
AAnnnnoonncceerr ddeess bboogguueess
Commencez par mettre en doute le probleme. Est-ce specifique a Linux
ou bien cela arrive avec gcc mais sur d'autres plates-formes ? Est-ce
specifique a la version du noyau ? A la version de la bibliotheque C ?
Est-ce que ce probleme disparait lorsque vous effectuez une edition de
liens statique ? Pouvez-vous produire un code tres court mettant en
evidence le probleme ?
Apres avoir repondu apres ces quelques questions, vous saurez quel
programme est a l'origine du probleme. Pour un probleme direct avec
GCC, le mieux est de consulter le fichier d'information livre avec :
la procedure pour rapporter un bogue y est detaille. Pour un probleme
avec ld.so, la bibliotheque C ou mathematique, envoyez un courrier
electronique a
[email protected]. Si possible, donnez un
court exemple mettant en evidence le probleme ainsi qu'une courte
description indiquant ce que le programme aurait normalement du faire,
et ce qu'il fait en realite.
88..22.. PPaarrttiicciippeerr aauu ddeevveellooppppeemmeenntt
Si vous desirez participer au developpement de GCC ou de la
bibliotheque C, la premiere chose a faire est de rejoindre la liste de
diffusion
[email protected]. Si vous desirez uniquement
savoir de quoi ca parle, il existe des archives a l'adresse
<
http://homer.ncm.com/linux-gcc/>. Tout depend de ce que vous desirez
faire ou apporter a ce projet !
99.. DDiivveerrss
99..11.. CCee ddooccuummeenntt
Ce HowTo est base sur la FAQ de Mitchum DSouza's. Bon nombre des
informations en proviennent. D'une maniere generale, il est frequent
de dire une phrase du genre " je n'ai pas tout teste et donc ne me
blamez pas si vous cassez votre disque, votre systeme ou si vous
rompez avec votre epouse ".
Le nom des contributeurs a ce document sont donnes par ordre
alphabetique : Andrew Tefft, Axel Boldt, Bill Metzenthen, Bruce Evans,
Bruno Haible, Daniel Barlow, Daniel Quinlan, David Engel, Dirk
Hohndel, Eric Youngdale, Fergus Henderson, H.J. Lu, Jens Schweikhardt,
Kai Petzke, Michael Meissner, Mitchum DSouza, Olaf Flebbe, Paul
Gortmaker, Rik Faith, Steven S. Dick, Tuomas J Lukka, et bien sur
Linus Torvalds, sans qui ce genre d'exercice aurait ete difficile,
voir impossible :-)
Ne soyez pas offense si votre nom n'apparait pas dans la liste et que
vous ayez contribue a ce document (sous la forme d'un HowTo ou d'une
FAQ). Envoyez-moi un courrier electronique et j'effectuerai la
correction.
99..22.. TTrraadduuccttiioonn
A l'heure ou j'ecris ces lignes, je ne connais pas de traduction de ce
document. Si vous en realisez une, s'il vous plait dites-le moi. Je
suis disponible pour toute aide concernant l'explication du texte, je
serai tres content d'y repondre.
Note du traducteur : CCooccoorriiccoo !! La version francaise est la premiere
traduction de ce document.
99..33.. CCoonnttaaccttss
Tout contact est le bienvenu. Envoyez-moi un courrier electronique a
l'adresse suivante :
[email protected]. Ma clef publique PGP
(ID 5F263625) est disponible sur mes pages WWW
<
http://ftp.linux.org.uk/~barlow/>, Si vous souhaitez rendre
confidentiel certains messages.
99..44.. CCooppyyrriigghhtt
Toutes les remarques appartiennent a leurs auteurs respectifs.
Ce document est copyrighte (C) 1996 Daniel Barlow
<
[email protected]>. Il peut etre reproduit et distribue en
partie ou entierement, sur tout support physique ou electronique, du
moment ou ce copyright se trouve sur toute les copies. La
redistribution commerciale est autorisee et encouragee. Toutefois
l'auteur de ce document doit etre mis au courant de ce genre de
distributions.
Toute traduction, adaptation, ou bien tout travail incorporant tout
document HowTo Linux doit posseder ce copyright. De cette maniere,
vous ne pouvez pas imposer de restriction a la distribution de ce
document. Des exceptions peuvent etre eventuellement accordees sous
certaines conditions : contactez le coordinateur des HowTo's Linux a
l'adresse donnee ci-dessous.
En resume, nous souhaitons voir diffuser l'information de la maniere
la plus large qui soit. Toutefois, nous souhaitons garder la maitrise
de ces documents et nous aimerions etre consultes avant toute
diffusion des HowTo's.
Si vous avez des questions, vous pouvez contacter Greg Hankins, le
coordinateur des HowTo Linux HOWTO a l'adresse electronique suivante :
[email protected]
1100.. IInnddeexx
Les entrees de cet index sont triees dans l'ordre alphabetique.
+o -fwritable-strings ``39'', ``56''
+o /lib/cpp ``16''
+o a.out ``1''
+o ar ``10''
+o as ``8''
+o <asm/*.h> ``19''
+o atoi() ``40''
+o atol() ``41''
+o executables trop gros ``63'', ``65'', ``77''
+o chewing gum ``3''
+o cos() ``68''
+o deboguer ``59''
+o divers ``72''
+o dlopen() ``82''
+o dlsym() ``83''
+o documentation ``4''
+o EINTR ``52''
+o elf ``0'', ``71''
+o execl() ``57''
+o fcntl ``47''
+o FD_CLR ``44''
+o FD_ISSET ``45''
+o FD_SET ``43''
+o FD_ZERO ``46''
+o fichier ``2''
+o <float.h> ``20''
+o gcc ``6''
+o gcc -fomit-frame-pointer ``61''
+o gcc -g ``60''
+o gcc -v ``14''
+o gcc, bogues ``15'', ``28'', ``29'', ``84''
+o gcc, options de compilation ``13'', ``25'', ``26''
+o gdb ``64''
+o fichiers d'en-tete ``17''
+o appels systemes interrompus ``51''
+o ld ``9''
+o LD_* : variables d'environnement ``80''
+o ldd ``81''
+o libc ``7''
+o libg.a ``62''
+o libgcc ``79''
+o <limits.h> ``21''
+o lint ``58''
+o <linux/*.h> ``18''
+o <math.h> ``70''
+o maths ``69''
+o mktemp() ``55''
+o numero de version ``12'', ``74''
+o optimisation ``27''
+o pages de manuel ``5''
+o QMAGIC ``76''
+o segmentation fault ``30'', ``54''
+o segmentation fault, in GCC ``33''
+o select() ``50''
+o SIGBUS ``34''
+o SIGEMT ``35''
+o SIGIOT ``36''
+o SIGSEGV ``31'', ``53''
+o SIGSEGV, in gcc ``32''
+o SIGSYS ``38''
+o SIGTRAP ``37''
+o sin() ``67''
+o soname ``73''
+o sprintf() ``42''
+o binaires linkes statiquement ``66'', ``78''
+o <stdarg.h> ``23''
+o <stddef.h> ``24''
+o strings ``11''
+o <sys/time.h> ``48''
+o <unistd.h> ``49''
+o <varargs.h> ``22''
+o ZMAGIC ``75''