<!-- GCC-Howto - version francaise : Eric Dumas               -->
<!-- Remarque : a la difference de la version originale      -->
<!--   certains commentaires plutot inutiles ont ete retires -->
<!--                       Eric.Dumas@freenix.fr             -->

<!doctype linuxdoc system>   

<article>

<title>GCC HOWTO pour Linux
<author>par Daniel Barlow <tt>&lt;dan@detached.demon.co.uk&gt;</tt>
<date>v1.17, 28 f&eacute;vrier 1996

<abstract>
(Adaptation fran&ccedil;aise par Eric Dumas <tt>&lt;dumas@freenix.fr&gt;</tt>, 
8 Avril 1996).

Ce document pr&eacute;sente la mani&egrave;re de configurer le compilateur GNU C et les
biblioth&egrave;ques de d&eacute;veloppement sous Linux. Il donne un aper&ccedil;u 
de la compilation, de l'&eacute;dition de liens, de l'ex&eacute;cution et du 
d&eacute;bogage de programmes sous Linux. Bon nombre de passages de ce
document sont emprunt&eacute;s &agrave; la FAQ GCC r&eacute;dig&eacute;e par Mitch D'Souza's et 
au HowTo ELF. 

Ceci est la premi&egrave;re version publique (en d&eacute;pit du num&eacute;ro de version :
en fait, &ccedil;a vient de RCS). N'h&eacute;sitez pas &agrave; me joindre pour toute remarque.
</abstract>

<sect>Pr&eacute;liminaires

<sect1> ELF et a.out
<label id="index.0"> <!-- elf -->
<label id="index.1"> <!-- a.out -->

<p> Le d&eacute;veloppement de Linux est actuellement dans une phase de transition.
En r&eacute;sum&eacute;, il existe deux formats de binaires que Linux reconna&icirc;t et
ex&eacute;cute, et cela d&eacute;pend de la mani&egrave;re dont votre syst&egrave;me est configur&eacute; :
vous pouvez avoir les deux, l'un ou l'autre. En lisant ce document,
vous pourrez savoir quels binaires votre syst&egrave;me est capable de g&eacute;rer.

<label id="index.2"> <!-- <tt/file/ -->

Comment le savoir ? Utilisez la commande <tt>file</tt> (par exemple,
<tt>file /bin/bash</tt>). Pour un programme ELF, cette commande va
vous r&eacute;pondre quelque chose dans lequel se trouve le mot ELF. Dans le cas
d'un programme en a.out, il vous indiquera quelque chose comme
<tt>Linux/i386</tt>.

Les diff&eacute;rences entre ELF et a.out sont d&eacute;taill&eacute;es plus tard dans
ce document. ELF est le nouveau format et il est consid&eacute;r&eacute; comme
&eacute;tant meilleur.

<sect1> Du c&ocirc;t&eacute; du copyright

<label id="index.3"> <!-- chewing gum -->
<p>
Le copyright et autres informations l&eacute;gales peuvent &ecirc;tre trouv&eacute;s &agrave; la 
<em/fin/ de ce document, avec les avertissements conventionnels concernant
la mani&egrave;re de poser des questions sur Usenet pour &eacute;viter d'avoir &agrave; r&eacute;v&eacute;ler
votre ignorance du langage C en annon&ccedil;ant des bogues qui n'en sont pas, etc.

<sect1> Typographie

<p> Si vous lisez ce document au format Postscript, dvi, ou HTML, vous
pouvez voir quelques diff&eacute;rence entre les styles d'&eacute;criture alors que les
gens qui consultent ce document au format texte pur ne verront aucune
diff&eacute;rence. En particulier, les noms de fichiers, le nom des commandes, 
les messages donn&eacute;s par les programmes et les codes sources seront 
&eacute;crits avec le style suivant : <tt/style d'&eacute;criture/, alors que
les noms de variables entre autres choses seront en <em/italique/.

Vous aurez &eacute;galement un index. Avec les formats dvi ou postscript, les
chiffres dans l'index correspondent au num&eacute;ros de paragraphes.
Au format HTML, il s'agit d'une num&eacute;rotation s&eacute;quentielle pour que
vous puissiez cliquer dessus. Avec le format texte, ce ne sont que des
nombres. Il vous est donc conseill&eacute; de prendre un autre format que le 
format texte !

L'interpr&eacute;teur de commande (<em>shell</em>) utilis&eacute; dans les exemples 
sera la Bourne shell (plut&ocirc;t que le C-Shell). Les utilisateurs du
C-Shell utiliseront plut&ocirc;t :
<tscreen><verb>
% setenv soif JD
</verb></tscreen>
l&agrave; o&ugrave; j'ai &eacute;crit
<tscreen><verb>
$ soif=JD; export soif
</verb></tscreen>

Si l'invite (<em>prompt</em> dans la langue de Shakespeare)
est  <tt/#/ plut&ocirc;t que <tt/&dollar;/, la commande ne fonctionnera
que si elle est ex&eacute;cut&eacute;e au nom de Root. Bien sur, je d&eacute;cline 
toute responsabilit&eacute; de ce qui peut se produire sur votre syst&egrave;me
lors de l'ex&eacute;cution de ces exemples. Bonne chance <tt/:-)/

<sect>O&ugrave; r&eacute;cup&eacute;rer de la documentation et les programmes ?

<sect1>Ce document

<p> Ce document fait partie de la s&eacute;rie des HOWTO pour Linux, et il est
donc disponible ainsi que ces coll&egrave;gues dans les r&eacute;pertoires HowTo pour 
Linux, comme sur <url
url="http://sunsite.unc.edu/pub/linux/docs/HOWTO/">.  La version HTML
peut &eacute;galement &ecirc;tre consult&eacute;e sur <url
url="http://ftp.linux.org.uk/~barlow/howto/gcc-howto.html">.

Note du traducteur : vous pouvez obtenir tous les HowTos en langue 
anglaise et fran&ccedil;aise sur <tt>ftp.ibp.fr:/pub/linux</tt>. Les versions
fran&ccedil;aises se trouvent dans le r&eacute;pertoire <tt>/pub/linux/french/HOWTO</tt>.


<sect1> Autres documentation
<label id="index.4"> <!-- documentation -->

<p> 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 <tt/.info/. Si vous poss&eacute;dez une connexion rapide, un CD-ROM
ou une certaine patience, vous pouvez d&eacute;sarchiver la documentation et 
l'installer dans le r&eacute;pertoire <tt>/usr/info</tt>.  Sinon, vous
pouvez toujours les trouver sur <url url=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/" name="tsx-11">, mais
ce n'est pas n&eacute;cessairement toujours la derni&egrave;re version.

<label id="index.5"> <!-- pages de manuel -->

<p> Il existe deux sources de documentation pour la libc. La libc GNU
est fournie avec des fichiers info qui d&eacute;crivent assez pr&eacute;cis&eacute;ment
la libc Linux sauf pour la partie des entr&eacute;es-sorties.  Vous pouvez &eacute;galement
trouver sur <url name="sunsite"
url="ftp://sunsite.unc.edu/pub/Linux/docs/"> des documents &eacute;crits
pour Linux ainsi que la description de certaines appels syst&egrave;mes
(section 2) et certaines fonctions de la libc (section 3).

Note du traducteur : un b&eacute;mol concernant cette partie... La libc
Linux n'est pas GNU et tend &agrave; &ecirc;tre relativement diff&eacute;rente sur certains
points.

<sect1>GCC 
<label id="index.6"> <!-- gcc -->

<p> Il existe deux types de r&eacute;ponses

(a) La distribution officielle de GCC pour Linux peut 
toujours &ecirc;tre r&eacute;cup&eacute;r&eacute;e sous la forme de binaires (d&eacute;j&agrave; compil&eacute;e)
sur <url url=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">. Vous pouvez la 
trouver sur le miroir fran&ccedil;ais  <url url=
"ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">.
A l'heure o&ugrave; j'&eacute;cris ces lignes, la derni&egrave;re version est 
gcc 2.7.2 (<tt/gcc-2.7.2.bin.tar.gz/).

(b) La derni&egrave;re distribution des sources de GCC de la <em>Free Software
Foundation</em> peut-&ecirc;tre r&eacute;cup&eacute;r&eacute;e sur
<url name="prep.ai.mit.edu"
url="ftp://prep.ai.mit.edu/pub/gnu/"> ou
<url name="ftp.ibp.fr"
url="ftp://ftp.ibp.fr/pub/gnu/">.
Ce n'est pas toujours la m&ecirc;me version que celle pr&eacute;sent&eacute;e ci-dessus. 
Les mainteneurs de GCC pour Linux ont rendu la compilation de GCC plus
facile gr&acirc;ce &agrave; l'utilisation du script <tt/configure/ qui
effectue la configuration d'une mani&egrave;re automatique. 
Regardez dans <url name="tsx-11" url=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"> ou
<url name="ftp.ibp.fr" url=
"ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">
pour r&eacute;cup&eacute;rer d'&eacute;ventuels patches.


Quelle que soit la complexit&eacute; de votre programme, vous aurez &eacute;galement
besoin de la <em>libc</em>.

<sect1> Les fichiers d'en-t&ecirc;te et la biblioth&egrave;que C
<label id="index.7"> <!-- libc -->

<p>Ce que vous allez trouver dans ce paragraphe d&eacute;pend 
<itemize>
<item> de votre syst&egrave;me (ELF ou a.out) ;
<item> du type de binaire que vous d&eacute;sirez g&eacute;n&eacute;rer.
</itemize>
Si vous &ecirc;tes en train de mettre &agrave; jour votre libc 4 en libc 5,
vous devriez consulter le ELF HowTo qui se trouve au m&ecirc;me
endroit que ce document.

Les libc sont disponibles sur <url name ="tsx-11" url=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/"> ou
<url name ="ftp.ibp.fr" url=
"ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">. Voici une description
des fichiers situ&eacute;s dans ce r&eacute;pertoire :

<descrip>

<tag/<tt/libc-5.2.18.bin.tar.gz// --- biblioth&egrave;ques dynamiques et statiques
ELF plus les fichiers d'en-t&ecirc;te pour la biblioth&egrave;que C et la biblioth&egrave;que
math&eacute;matique.

<tag/<tt/libc-5.2.18.tar.gz// --- Code source pour la biblioth&egrave;que ci-dessus.
Vous aurez &eacute;galement besoin du paquetage <tt>.bin.</tt> pour avoir les
fichiers d'en-t&ecirc;te. Si vous h&eacute;sitez entre compiler la biblioth&egrave;que C vous-m&ecirc;me
et utiliser les binaires, la bonne r&eacute;ponse est dans la majorit&eacute; des 
cas est d'utiliser les binaires. Toutefois, si vous d&eacute;sirer utiliser
NYS (NdT : NYS != NIS)  ou bien les mots de passe <em>shadow</em>,
vous devrez recompiler la libc par vous-m&ecirc;me.

<tag/<tt/libc-4.7.5.bin.tar.gz// --- biblioth&egrave;ques dynamiques et statiques 
a.out pour la version  4.7.5 de la libc.  Cette biblioth&egrave;que a 
&eacute;t&eacute; con&ccedil;ue pour pouvoir coexister avec le paquetage de la libc 5 d&eacute;crit
ci-dessus, mais c'est uniquement n&eacute;cessaire si vous d&eacute;sirez
utiliser ou d&eacute;velopper des programmes au format a.out.
</descrip>

<sect1>Outils associ&eacute;s (as, ld, ar, strings, etc.)

<label id="index.8"> <!-- <tt/as/ -->
<label id="index.9"> <!-- <tt/ld/ -->
<label id="index.10"> <!-- <tt/ar/ -->
<label id="index.11"> <!-- <tt/strings/ -->

<p>Ces outils se trouvent comme les biblioth&egrave;ques dans le r&eacute;pertoire
<url name ="tsx-11" url=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">, et
<url name ="ftp.ibp.fr" url=
"ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">.
La version actuelle est <tt/binutils-2.6.0.2.bin.tar.gz/.

<p> 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 probl&egrave;me lorsqu'elle est utilis&eacute;e avec la libc ELF.
Le d&eacute;veloppement de la libc est relativement rapide et &agrave; moins
que n'ayez de bonnes raisons pour utiliser le format a.out,
vous &ecirc;tes encourag&eacute;s &agrave; suivre le mouvement.

<sect>Installation et configuration de GCC 

<sect1>Les versions de GCC

<label id="index.12"> <!-- num&eacute;ros de version -->
<label id="index.13"> <!-- gcc, flags -->
<label id="index.14"> <!-- gcc -v -->

<p> Vous pouvez savoir quelle est la version de GCC que vous poss&eacute;dez en
tapant <tt>gcc -v</tt> lors de l'invite. C'est &eacute;galement une bonne
technique pour savoir si votre configuration est ELF ou a.out.
Sur mon syst&egrave;me, cela donne ceci :
<tscreen><verb>
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-zorglub-linux/2.7.2/specs
gcc version 2.7.2
</verb></tscreen>

<p> Les mots-clefs &agrave; remarquer
<itemize>
<item> <tt/i486/.  Cela vous indique que la version de gcc que vous utilisez 
a &eacute;t&eacute; compil&eacute;e pour &ecirc;tre utilis&eacute;e sur un processeur 486 --- mais vous pouvez
avoir un autre processeur comme un 386 ou un Pentium (586).
Tous ces processeurs peuvent ex&eacute;cuter le code compil&eacute; avec n'importe 
quel processeur. La seule diff&eacute;rence r&eacute;side dans le fait que le 
code 486 rajoute  un peu de code &agrave; certains endroits pour
aller plus vite sur un 486. Cela n'a pas d'effet n&eacute;faste c&ocirc;t&eacute;
performance sur un 386 mais cela rend les ex&eacute;cutables un peu plus
importants.

<item> <tt/zorglub/.  Ce n'est pas r&eacute;ellement important, et il s'agit 
g&eacute;n&eacute;ralement d'un commentaire (comme <tt/slackware/ or <tt/debian/) 
ou m&ecirc;me, cela peut-&ecirc;tre vide (lorsque vous avez comme nom
de r&eacute;pertoire  <tt/i486-linux/).  Si vous construisez votre propre
gcc, vous pouvez fixer ce param&egrave;tre selon vos d&eacute;sirs, comme je l'ai fait.
<tt/:-)/

<item> <tt/linux/.  Cela peut &ecirc;tre &agrave; la place <tt/linuxelf/ ou
<tt/linuxaout/ et en fait, la signification varie en fonction de la
version que vous poss&eacute;dez.

<itemize>
<item> <tt/linux/ signifie ELF si la version est 2.7.0 ou sup&eacute;rieure, sinon,
c'est du a.out.

<item><tt/linuxaout/ signifie a.out.  Cela a &eacute;t&eacute; introduit comme
cible lorsque le format des binaires a chang&eacute; de a.out vers ELF
dans <bf>Linux</bf>. Normalement, vous ne verrez plus de 
<tt/linuxaout/ avec une version de gcc sup&eacute;rieure &agrave; 2.7.0.

<label id="index.15"> <!-- gcc, bugs -->
<item><tt/linuxelf/ est d&eacute;pass&eacute;. Il s'agit g&eacute;n&eacute;ralement de gcc version
2.6.3 configur&eacute; pour g&eacute;n&eacute;rer des ex&eacute;cutables ELF. Notez que gcc 2.6.3
est connu pour g&eacute;n&eacute;rer de nombreuses erreurs lorsqu'il produit du code
ELF --- une mise &agrave; jour est tr&egrave;s fortement recommand&eacute;e.

</itemize>
<item> <tt/2.7.2/ est le num&eacute;ro de la version de GCC.
</itemize>

Donc, en r&eacute;sum&eacute;, nous poss&eacute;dons gcc 2.7.2 qui g&eacute;n&egrave;re du code ELF.  
<em>Quelle surprise</em> (NdT: En fran&ccedil;ais dans le texte) !

<sect1> A quel endroit s'installe GCC ? 

<p>Si vous avez install&eacute; gcc sans regarder, ou bien si vous l'avez eu
&agrave; partir d'une distribution, vous pouvez avoir envie de savoir
o&ugrave; il se trouve dans votre arborescence. Les mots clefs 
permettant cela sont

<itemize>
<item> <tt>/usr/lib/gcc-lib/</tt><em>machine-cible</em><tt>/</tt><em/version/<tt>/</tt> (et ses sous-r&eacute;pertoires) 
est g&eacute;n&eacute;ralement l'endroit o&ugrave; se trouve le plus souvent le compilateur.
Ceci inclut les ex&eacute;cutables qui r&eacute;alisent la compilation ainsi
que certaines biblioth&egrave;ques et quelques fichiers d'en-t&ecirc;te.

<item> <tt>/usr/bin/gcc</tt> est le lanceur du compilateur --- 
c'est en fait le programme que vous lancez.  Il peut &ecirc;tre utilis&eacute;
avec plusieurs versions de gcc lorsque vous poss&eacute;dez plusieurs r&eacute;pertoires
install&eacute;s (voir plus bas). Pour trouver la version par d&eacute;faut utilis&eacute;e, 
lancez <tt/gcc -v/.  Pour forcer l'utilisation d'une autre
version, lancez <tt/gcc -V /<em/version/. Par exemple,

<tscreen><verb>
# 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
</verb></tscreen>

<item> <tt>/usr/</tt><em>machine-cible</em><tt>/(bin|lib|include)/</tt>. 
Si vous avez install&eacute; plusieurs cibles possibles (par exemple a.out et elf, 
ou bien un compilateur crois&eacute;, les biblioth&egrave;ques, les binutils 
(<tt/as/, <tt/ld/, etc.) et les fichiers d'en-t&ecirc;te  pour 
les cibles diff&eacute;rente de celle par d&eacute;faut peuvent &ecirc;tre trouv&eacute;s &agrave; cet endroit.
M&ecirc;me si vous n'avez qu'une seule version de gcc install&eacute;e, vous devriez
toutefois trouver &agrave; cet endroit un certain nombre de fichiers. Si ce n'est pas
la cas, regardez dans <tt>/usr/(bin|lib|include)</tt>.

<item> <tt>/lib/</tt>, <tt>/usr/lib</tt> et autres sont les r&eacute;pertoires
pour les biblioth&egrave;ques pour le syst&egrave;me initial. Vous aurez &eacute;galement besoin
du programme <tt>/lib/cpp</tt> pour un grand nombre d'applications
(X l'utilise beaucoup) --- soit vous le copiez &agrave; partir de 
<tt>/usr/lib/gcc-lib/</tt><em>machine-cible</em><tt>/</tt><em/version/<tt>/</tt>, soit vous faites  pointer un lien symbolique dessus.

<label id="index.16"> <!-- /lib/cpp -->
</itemize>

<sect1> O&ugrave; se trouvent les fichiers d'en-t&ecirc;te ?
<label id="index.17"> <!-- fichiers d'en-t&ecirc;te -->

<p>Si l'on excepte les fichier fichiers d'en-t&ecirc;te que vous installez
dans le r&eacute;pertoire <tt>/usr/local/include</tt>,  il y a en fait
trois types de fichiers d'en-t&ecirc;te :

<itemize>

<item> La grande majorit&eacute; des fichiers situ&eacute;s dans le r&eacute;pertoire
<tt>/usr/include/</tt> et dans ses sous-r&eacute;pertoires proviennent 
du paquetage de la libc dont s'occupe H.J. Lu. Je dis bien
la <sq>grande  majorit&eacute;</sq> car vous pouvez avoir &eacute;galement certains 
fichiers provenant d'autres sources (par exemple des 
biblioth&egrave;ques <tt/curses/ et <tt/dbm/), ceci est d'autant plus vrai 
si vous poss&eacute;dez une distribution de la libc 
r&eacute;cente (o&ugrave; les biblioth&egrave;ques curses et dbm ne sont pas int&eacute;gr&eacute;es).

<label id="index.18"> <!-- &lt;linux/*.h&gt; -->
<label id="index.19"> <!-- &lt;asm/*.h&gt; -->

<item> Les r&eacute;pertoires <tt>/usr/include/linux</tt> 
et <tt>/usr/include/asm</tt> (pour les fichiers
<tt>&lt;linux/*.h&gt;</tt> et <tt>&lt;asm/*.h&gt;</tt>)
doivent &ecirc;tre des liens symboliques vers les r&eacute;pertoires
<tt>linux/include/linux</tt> et <tt>linux/include/asm</tt> situ&eacute;s dans
les sources du noyau. Vous devrez installer ces sources si vous d&eacute;sirez
pouvoir d&eacute;velopper : ces sources ne sont pas utilis&eacute;s uniquement
pour compiler le noyau.

Il est probable que vous ayez besoin de lancer la commande suivante
<tt>make config</tt> dans le r&eacute;pertoire des sources du noyau
apr&egrave;s les avoir install&eacute;s. Beaucoup de fichiers ont besoin
du fichier d'en-t&ecirc;te <tt>&lt;linux/autoconf.h&gt;</tt> 
qui n'existe pas sans cette commande. Il est &agrave; noter que dans 
certaines versions du noyau, le r&eacute;pertoire <tt/asm/ 
est en fait un lien symbolique qui n'est cr&eacute;&eacute; qu'avec l'ex&eacute;cution de
<tt/make config/.

Donc, si vous installez les sources du noyau dans le r&eacute;pertoire
<tt>/usr/src/linux</tt>, il suffit de faire :
<tscreen><verb>
$ 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 .
</verb></tscreen>

<label id="index.20"> <!-- &lt;float.h&gt -->
<label id="index.21"> <!-- &lt;limits.h&gt; -->
<label id="index.22"> <!-- &lt;varargs.h&gt; -->
<label id="index.23"> <!-- &lt;stdarg.h&gt; -->
<label id="index.24"> <!-- &lt;stddef.h&gt; -->


<item> Les fichiers tels que <tt/&lt;float.h&gt;/, <tt/&lt;limits.h&gt;/,
<tt/&lt;varargs.h&gt;/, <tt/&lt;stdarg.h&gt;/ et
<tt/&lt;stddef.h&gt;/ changent en fonction de la version du compilateur, et
peuvent &ecirc;tre trouv&eacute;s dans le r&eacute;pertoire 
<tt>/usr/lib/gcc-lib/i486-box-linux/2.7.2/include/</tt> pour la version
<tt>2.7.2</tt>.

</itemize>

<sect1> Construire un compilateur crois&eacute;

<sect2> Linux comme plate-forme de destination

<p> Nous supposons que vous avez r&eacute;cup&eacute;r&eacute; les sources de gcc, et normalement,
il vous suffit de suivre les instructions donn&eacute;es dans le fichier 
<tt>INSTALL</tt> situ&eacute; dans les sources de gcc. Ensuite, il suffit de lancer
<tt>configure --target=i486-linux --host=XXX</tt> sur une plateforme <tt/XXX/,
puit un <tt/make/ devrait compiler gcc correctement. Il est &agrave; noter 
que vous aurez besoin des fichiers d'en-t&ecirc;te de Linux, ainsi que les sources
de l'assembleur et du l'&eacute;diteur de liens crois&eacute;s que vous pouvez trouver
sur <url url="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/"> ou
<url url="ftp://ftp.ibp.fr/pub/linux/GCC/">.

<sect2> Linux comme plate-forme origine et MSDOS comme destination

<p> Arggg.  Apparemment, cela est possible en utilisant
le paquetage « emx » ou l'extension « go ». Regardez <url
url="ftp://sunsite.unc.edu/pub/Linux/devel/msdos"> pour plus 
d'informations.

Je n'ai pas test&eacute; cela et je ne pense pas le faire !

<sect>Portage et compilation

<sect1> Symboles d&eacute;finis automatiquement
<label id="index.25"> <!-- gcc, options de compilation -->

<p>Vous pouvez trouver quels symboles votre version de gcc d&eacute;finit
automatiquement en le lan&ccedil;ant avec l'option <tt/-v/.
Par exemple cela donne &ccedil;a chez moi :
<tscreen><verb>
$ 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__ -
</verb></tscreen>
Si vous &eacute;crivez du code qui utilise des sp&eacute;cificit&eacute;s Linux, il
est souhaitable d'impl&eacute;menter le code non portable de la mani&egrave;re suivante 
<tscreen><verb>
#ifdef __linux__
/* ... code linux ... */
#endif /* linux */
</verb></tscreen>

Utilisez <tt>__linux__</tt> pour cela, et <em/pas/ <tt/linux/.
Bien que cette macro soit d&eacute;finie, ce n'est pas une sp&eacute;cification POSIX.

<sect1> Options de compilation

<p> La documentation des options de compilation se trouve dans les 
pages <em>info</em> de gcc (sous Emacs, utilisez <tt>C-h i</tt> puis
s&eacute;lectionnez l'option `gcc').  Votre distribution peut ne pas 
avoir install&eacute; la documentation ou bien vous pouvez en avoir une
ancienne. Dans ce cas, la meilleure chose &agrave; faire est de r&eacute;cup&eacute;rer
les sources de gcc depuis <url url="ftp://prep.ai.mit.edu/pub/gnu"> ou
l'un des ses nombreux miroirs dont <url url="ftp://ftp.ibp.fr/pub/gnu">.

La page de manuel gcc (<tt/gcc.1/) est en principe, compl&egrave;tement 
d&eacute;pass&eacute;e. Cela vous met en garde si vous d&eacute;sirez la consulter.

<sect2> Options de compilation
<label id="index.26"> <!-- gcc, options de compilations -->
<label id="index.27"> <!-- optimisation -->

<p> gcc peut r&eacute;aliser un certain nombre d'optimisations sur le code g&eacute;n&eacute;r&eacute; 
en ajoutant l'option <tt/-O/<em/n/ &agrave; la ligne de commandes, o&ugrave;
<em/n/ est un chiffre. La valeur de <em/n/, et son effet exact, 
d&eacute;pend de la version de gcc, mais s'&eacute;chelonne normalement entre
0 (aucune optimisation) et 2 (un certain nombre) ou 3 (toutes les
optimisations possibles).

En interne, gcc interpr&egrave;te les options telles que <tt/-f/ et <tt/-m/.  
Vous pouvez voir exactement ce qu'effectue le niveau sp&eacute;cifi&eacute; dans 
l'option <tt/-O/ en lan&ccedil;ant gcc avec l'option <tt/-v/ 
et l'option (non document&eacute;e)
<tt/-Q/.  Par exemple, l'option <tt/-O2/, effectue les op&eacute;rations
suivantes sur ma machine :
<tscreen><verb>
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
</verb></tscreen>

Utiliser un niveau d'optimisation sup&eacute;rieur &agrave; celui que le compilateur 
supporte (par exemple <tt/-O6/) aura le m&ecirc;me effet qu'utiliser le plus 
haut niveau g&eacute;r&eacute;. Distribuer du code o&ugrave; la compilation est configur&eacute;e de
cette mani&egrave;re est une tr&egrave;s mauvaise id&eacute;e -- si d'autres optimisations
sont incorpor&eacute;es dans de versions futures, vous (ou d'autres utilisateurs)
pouvez vous apercevoir que cela ne compile plus, ou bien que le code
g&eacute;n&eacute;r&eacute; ne fait pas les actions d&eacute;sir&eacute;es.

<label id="index.28"> 
Les utilisateurs de gcc 2.7.0 &agrave; 2.7.2 devraient noter qu'il y a un
bogue dans l'option <tt/-O2/. Plus pr&eacute;cis&eacute;ment, la 
<em>strength reduction</em> ne fonctionne pas.  Un patch a &eacute;t&eacute; 
impl&eacute;ment&eacute; pour r&eacute;soudre ce probl&egrave;me, mais vous devez alors 
recompiler gcc. Sinon, vous devrez toujours compiler avec l'option
<tt/-fno-strength-reduce/.


<sect3>Sp&eacute;cification du processeur<p>

<p> Il existe d'autres options <tt/-m/ qui ne sont pas positionn&eacute;es
lors de l'utilisation de <tt/-O/ mais qui sont n&eacute;anmoins utiles dans certains
cas. C'est le cas pour les options <tt/-m386/ et <tt/-m486/, 
qui indiquent &agrave; gcc de g&eacute;n&eacute;rer un code plus ou moins optimis&eacute;
pour l'un ou l'autre type de processeur. Le code continuera &agrave; fonctionner
sur les deux processeurs. Bien que le code pour 486 soit plus important, il
ne ralentit pas l'ex&eacute;cution du programme sur 386.

Il n'existe pas actuellement de <tt/-mpentium/ ou <tt/-m586/.  Linus 
a sugg&eacute;r&eacute; l'utilisation des options 
<tt/-m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2/,
pour exploiter les optimisations du 486 tout en perdant de la place
due aux probl&egrave;mes d'alignements (dont le Pentium n'a que faire). 
Michael Meissner (de Cygnus) nous dit :

<quote>
« Mon avis est que l'option <tt> -mno-strength-reduce </tt> permet 
d'obtenir un code plus rapide sur un x86 (nota : je ne parle pas
du bogue <em>strength reduction</em>, qui est un autre probl&egrave;me). 
Cela s'explique en raison du peu de registres dont disposent ces processeurs
(et la m&eacute;thode de GCC qui consiste &agrave; grouper les registres dans l'ordre 
inverse au lieu d'utiliser d'autres registres n'arrange rien).
La <em>strength reduction</em> consiste en fait &agrave; rajouter 
des registres pour remplacer les multiplications par des additions.
Je suspecte &eacute;galement <tt> -fcaller-saves</tt> de ne pas arranger la 
situation. »
</quote>

<quote>
Une autre id&eacute;e est que <tt/-fomit-frame-pointer/ n'est pas obligatoirement
une bonne id&eacute;e.  
D'un c&ocirc;t&eacute;, cela peut signifier qu'un autre registre est disponible
pour une allocation. D'un autre c&ocirc;t&eacute;, vue la mani&egrave;re 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 fen&ecirc;tres relatives, ce qui signifie en clair 
que moins de cache est disponible pour l'ex&eacute;cution du processus.
Il faut pr&eacute;ciser que l'option <tt/-fomit-frame-pointer/, signifie
que le compilateur doit constamment ajuster le pointeur de pile apr&egrave;s les
appels, alors qu'avec une fen&ecirc;tre, il peut laisser plusieurs appels 
dans la pile.
</quote>

Le mot final sur le sujet provient de Linus :

<quote>
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 r&eacute;elle optimisation que pour vous.
</quote>

<sect2> <tt/Internal compiler error: cc1 got fatal signal 11/

<label id="index.29"> <!-- gcc, bugs -->
<label id="index.30"> <!-- segmentation fault -->
<label id="index.31"> <!-- SIGSEGV -->
<label id="index.32"> <!-- SIGSEGV, in gcc -->
<label id="index.33"> <!-- segmentation fault, dans GCC -->

<p> Signal 11 correspond au signal SIGSEGV, ou bien <em>segmentation 
violation</em>. Normalement, cela signifie que le programme s'est m&eacute;lang&eacute;
les pointeurs et a essay&eacute; d'&eacute;crire l&agrave; o&ugrave; il n'en a pas le droit. Donc, cela
pourrait &ecirc;tre un bug de gcc.

Toutefois, gcc est un logiciel assez test&eacute; et assez remarquable de ce c&ocirc;t&eacute;.
Il utilise un grand nombre de structures de donn&eacute;es complexes, et un
nombre impressionnant de pointeurs. En r&eacute;sum&eacute;, c'est le plus pointilleux
des testeurs de m&eacute;moire existants. Si vous <em/n'arrivez pas &agrave; reproduire le 
bogue/ 
--- si cela ne s'arr&ecirc;te pas au m&ecirc;me endroit lorsque vous retentez la 
compilation --- c'est plut&ocirc;t un probl&egrave;me avec votre machine (processeur,
m&eacute;moire, carte m&egrave;re ou bien cache). <bf>N'annoncez pas</bf> la d&eacute;couverte
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 m&ecirc;me si le noyau s'arr&ecirc;te lors du
`<tt/make zImage/' !  `<tt/make zImage/'
doit compiler plus de 200 fichiers, et il en faut bien moins pour arriver
&agrave; faire &eacute;chouer une compilation.

<p> Si vous arrivez &agrave; reproduire le bogue et (mieux encore) &agrave; &eacute;crire un
petit programme qui permet de mettre en &eacute;vidence cette erreur, alors
vous pouvez envoyer le code soit &agrave; la FSF, soit dans la liste linux-gcc.
Consultez la documentation de gcc pour plus de d&eacute;tails concernant les
informations n&eacute;cessaires.

<sect1>Portabilit&eacute;

<p> Cette phrase a &eacute;t&eacute; dite un jour : si quelque chose n'a pas &eacute;t&eacute;
port&eacute; vers Linux alors ce n'est pas important de l'avoir :-).

Plus s&eacute;rieusement, en g&eacute;n&eacute;ral seules quelques modifications mineures sont
n&eacute;cessaires car Linux r&eacute;pond &agrave; 100% aux sp&eacute;cifications POSIX.
Il est g&eacute;n&eacute;ralement sympathique d'envoyer &agrave; l'auteur du programme
les modifications effectu&eacute;es pour que le programme fonctionne sur Linux, pour
que lors d'une future version, un `make' suffise pour g&eacute;n&eacute;rer l'ex&eacute;cutable.

<sect2> Sp&eacute;cificit&eacute;s BSD (notamment <tt/bsd_ioctl/, <tt/daemon/ et
<tt/&lt;sgtty.h&gt;/)

<p> Vous pouvez compiler votre programme avec l'option
<tt>-I/usr/include/bsd</tt> et faire l'&eacute;dition de liens avec <tt>-lbsd</tt> 
(en ajoutant <tt>-I/usr/include/bsd</tt> &agrave; la ligne <tt>CFLAGS</tt>
et <tt>-lbsd</tt> &agrave; la ligne <tt>LDFLAGS</tt> dans votre fichier
<tt>Makefile</tt>). Il est &eacute;galement n&eacute;cessaire de ne <bf>pas</bf>
ajouter <tt>-D__USE_BSD_SIGNAL</tt> si vous voulez 
que les signaux BSD fonctionnent car vous les avez inclus automatiquement
avec la ligne
<tt>-I/usr/include/bsd</tt> et en incluant le fichier d'en-t&ecirc;te
<tt/&lt;signal.h&gt;/.

<sect2> Signaux <em>manquants</em> 
(<tt/SIGBUS/, <tt/SIGEMT/, <tt/SIGIOT/, <tt/SIGTRAP/, <tt/SIGSYS/, etc.)
<label id="index.34"> <!-- <tt/SIGBUS/ -->
<label id="index.35"> <!-- <tt/SIGEMT/ -->
<label id="index.36"> <!-- <tt/SIGIOT/ -->
<label id="index.37"> <!-- <tt/SIGTRAP/ -->
<label id="index.38"> <!-- <tt/SIGSYS/ -->

<p> Linux respecte les sp&eacute;cifications 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) :

<quote>
« Les signaux SIGBUS, SIGEMT, SIGIOT, SIGTRAP, et SIGSYS ont &eacute;t&eacute; omis 
de la norme POSIX.1 car leur comportement est d&eacute;pendant de l'impl&eacute;mentation
et donc ne peut &ecirc;tre r&eacute;pertori&eacute; d'une mani&egrave;re satisfaisante.
Certaines impl&eacute;mentations peuvent fournir ces signaux mais doivent
documenter leur effet »
</quote>

<p>La mani&egrave;re la plus &eacute;l&eacute;gante de r&eacute;gler ce probl&egrave;me est de
red&eacute;finir ces signaux &agrave; <tt/SIGUNUSED/.  La mani&egrave;re <em/normale/ de 
proc&eacute;der est d'entourer le code avec les <tt/#ifdef/ appropri&eacute;s :

<tscreen><verb>
#ifdef SIGSYS
/* ... code utilisant les signaux non posix  .... */
#endif
</verb></tscreen>

<sect2> Code K &amp; R
<label id="index.39"> <!-- <tt/-fwritable-strings/ -->

<p> GCC est un compilateur ANSI, or il existe beaucoup de code
qui ne soit pas ANSI. 

Il n'y a pas grand chose &agrave; faire, sauf rajouter l'option
<tt/-traditional/ lors de la compilation. Il effectue certaines 
v&eacute;rifications suppl&eacute;mentaires. Consultez les pages info gcc.

Notez que l'option <tt/-traditional/ a pour unique effet de changer la forme
du langage accept&eacute; par gcc. Par exemple, elle active l'option
<tt>-fwritable-strings</tt>, qui d&eacute;place toutes les cha&icirc;nes de caract&egrave;res
vers l'espace de donn&eacute;es (depuis l'espace de texte, o&ugrave; elle ne 
peuvent pas &ecirc;tre modifi&eacute;es). Ceci augmente la taille de la m&eacute;moire 
occup&eacute;e par le programme.

<sect2> Les symboles du pr&eacute;processeur produisent un conflit avec
les prototypes du code
<label id="index.40"> <!-- <tt/atoi()/ -->
<label id="index.41"> <!-- <tt/atol()/ -->

<p> Un des probl&egrave;mes fr&eacute;quents se produit lorsque certaines fonctions
standards sont d&eacute;finies comme macros dans les fichiers d'en-t&ecirc;te
de Linux et le pr&eacute;processeur refusera de traiter 
des prototypes identiques. Par exemple, cela peut arriver
avec <tt/atoi()/ et <tt/atol()/.

<sect2> <tt>sprintf()</tt>
<label id="index.42"> <!-- <tt/sprintf()/ -->

<p> Parfois, soyez prudent lorsque vous effectuez un portage &agrave; partir
des sources de programmes fonctionnant sous SunOs, surtout avec 
la fonction <tt/sprintf(string, fmt, ...)/ car elle renvoie 
un pointeur sur la cha&icirc;ne de caract&egrave;res alors que Linux (suivant la norme ANSI)
retourne le nombre de caract&egrave;res recopi&eacute;s dans la cha&icirc;ne de caract&egrave;res.


<sect2> <tt/fcntl/ et ses copains.  O&ugrave; se trouve la d&eacute;finition de 
<tt/FD_*/ et compagnie ?
<label id="index.43"> <!-- <tt/FD_SET/ -->
<label id="index.44"> <!-- <tt/FD_CLR/ -->
<label id="index.45"> <!-- <tt/FD_ISSET/ -->
<label id="index.46"> <!-- <tt/FD_ZERO/ -->
<label id="index.47"> <!-- <tt/fcntl/ -->
<label id="index.48"> <!-- <tt>&lt;sys/time.h&gt;</tt> -->
<label id="index.49"> <!-- <tt>&lt;unistd.h&gt;</tt> -->

<p> Dans <tt>&lt;sys/time.h&gt;</tt>.  Si vous utilisez
<tt/fcntl/ vous voudrez probablement inclure 
<tt/&lt;unistd.h&gt;/ &eacute;galement, pour avoir le prototype de la fonction.

D'une mani&egrave;re g&eacute;n&eacute;rale, la page de manuel pour une fonction
donne la liste des fichiers d'en-t&ecirc;te &agrave; inclure.

<sect2> Le timeout de <tt>select()</tt>. Les programmes
commencent dans un &eacute;tat d'attente active
<label id="index.50"> <!-- select() -->

<P> A une certaine &eacute;poque, le param&egrave;tre timeout de la fonction 
<tt>select()</tt> &eacute;tait utilis&eacute; en lecture seule.  C'est pourquoi la page
de manuel comporte une mise en garde :

<quote>
select() devrait retourner normalement le temps &eacute;coul&eacute; depuis le
timeout initial, s'il s'est d&eacute;clench&eacute;, en modifiant la valeur point&eacute;e par
le param&egrave;tre <tt>time</tt>. Cela sera peut-&ecirc;tre impl&eacute;ment&eacute; dans les
versions ult&eacute;rieures du syst&egrave;me. Donc, il n'est pas vraiment prudent de 
supposer que les donn&eacute;es point&eacute;es ne seront pas modifi&eacute;es lors de l'appel
&agrave; select().
</quote>

Mais tout arrive avec le temps ! Lors d'un retour de 
<tt/select()/, l'argument <tt>timeout</tt> recevra le
temps &eacute;coul&eacute; depuis la derni&egrave;re r&eacute;ception de donn&eacute;es. Si aucune
donn&eacute;e n'est arriv&eacute;e, la valeur sera nulle, et les futurs
appels &agrave; cette fonction utilisant le m&ecirc;me <tt>timeout</tt>
auront pour r&eacute;sultat un retour imm&eacute;diat.

Pour r&eacute;soudre le probl&egrave;me, il suffit de mettre la valeur <tt>timeout</tt>
dans la structure &agrave; chaque appel de <tt/select()/.  
Le code initial &eacute;tait 
<tscreen><verb>
      struct timeval timeout;
      timeout.tv_sec = 1; 
      timeout.tv_usec = 0;
      while (some_condition)
            select(n,readfds,writefds,exceptfds,&ero;timeout); 
</verb></tscreen>
et doit devenir :
<tscreen><verb>
      struct timeval timeout;
      while (some_condition) 
      {
            timeout.tv_sec = 1; 
	    timeout.tv_usec = 0;
            select(n,readfds,writefds,exceptfds,&ero;timeout);
      }
</verb></tscreen>

Certaines versions de Mosaic &eacute;taient connues &agrave; une certaine &eacute;poque
pour avoir ce probl&egrave;me. 

La vitesse de rotation du globe terrestre &eacute;tait inversement
proportionnelle &agrave; la vitesse de transfert des donn&eacute;es !

<sect2> Appels syst&egrave;mes interrompus
<label id="index.51"> <!-- interrupted system calls -->
<label id="index.52"> <!-- EINTR -->

<sect3>Symptomes :

<p>Lorsqu'un processus est arr&ecirc;t&eacute; avec un Ctrl-Z et relanc&eacute; - ou bien
lorsqu'un autre signal est d&eacute;clench&eacute; dans une situation diff&eacute;rente : 
par exemple avec un Ctrl-C, la terminaison d'un processus, etc, on
dit qu'il y a « interruption d'un appel syst&egrave;me » , ou bien
« write : erreur inconnue » ou des trucs de ce genre.

<sect3>Probl&egrave;mes :

<p>Les syst&egrave;mes POSIX v&eacute;rifient les signaux plus souvent que 
d'autres Unix plus anciens. Linux peux lancer les gestionnaires
de signaux :
<itemize>
<item> d'une mani&egrave;re asynchrone (sur un top d'horloge)
<item> lors d'un retour de n'importe quel appel syst&egrave;me
<item> pendant l'ex&eacute;cution des appels syst&egrave;mes suivants :
<tt>select()</tt>, <tt>pause()</tt>, <tt>connect()</tt>,
<tt>accept()</tt>, <tt>read()</tt> sur des terminaux, des sockets, des pipes 
ou des fichiers situ&eacute;s dans <tt>/proc</tt>, <tt>write()</tt> sur des
terminaux, des sockets, des pipes ou des imprimantes, <tt>open()</tt> 
sur des FIFOs, des lignes PTYs ou s&eacute;ries,
<tt>ioctl()</tt> sur des terminaux, <tt>fcntl()</tt> avec la commande
<tt/F_SETLKW/, <tt>wait4()</tt>, <tt>syslog()</tt>, et toute op&eacute;ration
d'ordre TCP ou NFS.  
</itemize>

Sur d'autres syst&egrave;mes d'exploitation, il est possible que vous
ayez &agrave; inclure dans cette cat&eacute;gorie les appels syst&egrave;mes suivants :
<tt>creat()</tt>, <tt>close()</tt>, <tt>getmsg()</tt>, <tt>putmsg()</tt>,
<tt>msgrcv()</tt>, <tt>msgsnd()</tt>, <tt>recv()</tt>, <tt>send()</tt>,
<tt>wait()</tt>, <tt>waitpid()</tt>, <tt>wait3()</tt>, <tt>tcdrain()</tt>,
<tt>sigpause()</tt>, <tt>semop()</tt>.


<p>Si un signal (que le programme d&eacute;sire traiter) est lanc&eacute; pendant
l'ex&eacute;cution d'un appel syst&egrave;me, le gestionnaire est lanc&eacute;. Lorsque
le gestionnaire du signal se termine, l'appel syst&egrave;me d&eacute;tecte qu'il a &eacute;t&eacute;
interrompu et se termine avec la valeur -1 et <tt/errno = EINTR/. 
Le programme n'est pas forc&eacute;ment au courant de ce qui s'est pass&eacute; et
donc s'arr&ecirc;te.

Vous pouvez choisir deux solutions pour r&eacute;soudre ce probl&egrave;me.

(1)Dans tout gestionnaire de signaux que vous mettez en place, ajoutez
l'option <tt/SA_RESTART/ au niveau de <em>sigaction</em>. Par exemple, 
modifiez
<tscreen><verb>
  signal (signal_id, mon_gestionnaire_de_signaux);
</verb></tscreen>
en
<tscreen><verb>
  signal (signal_id, mon_gestionnaire_de_signaux);
  { 
	struct sigaction sa;
    	sigaction (signal_id, (struct sigaction *)0, &ero;sa);
#ifdef SA_RESTART
        sa.sa_flags |= SA_RESTART;
#endif
#ifdef SA_INTERRUPT
    	sa.sa_flags &ero;= ~ SA_INTERRUPT;
#endif
    	sigaction (signal_id, &ero;sa, (struct sigaction *)0);
  }
</verb></tscreen>

Notez que lors de certains appels syst&egrave;mes vous
devrez souvent regarder si <tt>errno</tt> n'a pas &eacute;t&eacute; positionn&eacute;e &agrave; 
<tt/EINTR/ par vous m&ecirc;me comme avec <tt/read()/, <tt/write()/,
<tt/ioctl()/, <tt/select()/, <tt/pause()/ et <tt/connect()/. 

(2) A la recherche de <tt/EINTR/ :

Voici deux exemples avec <tt/read()/ et <tt/ioctl()/,

Voici le code original utilisant <tt/read()/

<tscreen><verb>
int result;
while (len > 0) 
{ 
  result = read(fd,buffer,len);
  if (result < 0) 
	break;
  buffer += result; 
  len -= result;
}
</verb></tscreen>
et le nouveau code 

<tscreen><verb>
int result;
while (len > 0) 
{ 
  result = read(fd,buffer,len);
  if (result < 0) 
  { 
	if (errno != EINTR) 
		break; 
  }
  else 
  { 
	buffer += result; 
	len -= result; 
  }
}

</verb></tscreen>
Voici un code utilisant  <tt/ioctl()/

<tscreen><verb>
int result;
result = ioctl(fd,cmd,addr);
</verb></tscreen>
et cela devient
<tscreen><verb>
int result;
do 
{ 
   result = ioctl(fd,cmd,addr); 
}
while ((result == -1) && (errno == EINTR));
</verb></tscreen>

Il faut remarquer que dans certaines versions d'Unix de type BSD 
on a l'habitude de relancer l'appel syst&egrave;me. Pour r&eacute;cup&eacute;rer les interruptions
d'appels syst&egrave;mes, vous devez utiliser les options 
<tt/SV_INTERRUPT/ ou <tt/SA_INTERRUPT/.

<sect2> Les cha&icirc;nes et leurs acc&egrave;s en &eacute;critures (ou les programmes qui provoquent des
« segmentation fault » d'une mani&egrave;re al&eacute;atoire)
<label id="index.53"> <!-- SIGSEGV -->
<label id="index.54"> <!-- segmentation fault -->
<label id="index.55"> <!-- <tt/mktemp()/ -->
<label id="index.56"> <!-- <tt/-fwritable-strings/ -->

<p> GCC a une vue optimiste en ce qui concerne ses utilisateurs, en 
croyant qu'ils respectent le fait qu'une cha&icirc;ne dite constante l'est
r&eacute;ellement. Donc, il les range  dans la zone <em>texte(code)</em> du 
programme, o&ugrave; elles peuvent &ecirc;tre charg&eacute;es puis d&eacute;charg&eacute;es 
&agrave; partir de l'image binaire de l'ex&eacute;cutable situ&eacute;e sur disque (ce qui &eacute;vite
d'occuper de l'espace disque). Donc, toute tentative d'&eacute;criture dans 
cette cha&icirc;ne provoque un « segmentation
fault ».

Cela peut poser certains probl&egrave;mes avec d'anciens codes, par exemple
ceux qui utilisent la fonction <tt>mktemp()</tt> avec une cha&icirc;ne constante
comme argument.  <tt/mktemp()/ essaye d'&eacute;crire dans la cha&icirc;ne pass&eacute;e
en argument.

Pour r&eacute;soudre ce probl&egrave;me, 
<enum>
<item>compilez avec l'option <tt/-fwritable-strings/ pour indiquer
&agrave; gcc de mettre les cha&icirc;nes constantes dans l'espace de donn&eacute;es
<item> r&eacute;&eacute;crire les diff&eacute;rentes parties du code pour allouer 
une cha&icirc;ne non constante puis effectuer un strcpy des donn&eacute;es
dedans avant d'effectuer l'appel.
</enum>

<sect2>Pourquoi l'appel &agrave; <tt>execl()</tt> &eacute;choue ?
<label id="index.57"> <!-- <tt/execl()/ -->

<p> Tout simplement parce que vous l'utilisez mal. Le premier argument
d'<tt/execl/ est le programme que vous d&eacute;sirez ex&eacute;cuter. Le second et ainsi
de suite sont en fait le &eacute;l&eacute;ments du tableau <tt/argv/ que vous appelez.
Souvenez-vous que <tt/argv[0]/ est traditionnellement fix&eacute; m&ecirc;me si
un programme est lanc&eacute; sans argument. Vous devriez donc &eacute;crire :
<tscreen><verb>
execl("/bin/ls","ls",NULL);
</verb></tscreen>
et pas 
<tscreen><verb>
execl("/bin/ls", NULL);
</verb></tscreen>

<p> Lancer le programme sans argument est consid&eacute;r&eacute; comme &eacute;tant une
demande d'affichage des biblioth&egrave;ques dynamiques associ&eacute;es au programme,
si vous utilisez le format a.out. ELF fonctionne d'une mani&egrave;re diff&eacute;rente.

<p>(Si vous d&eacute;sirez ces informations, il existe des outils plus simples;
consultez la section sur le chargement dynamique, ou la page de manuel
de <tt/ldd/).


<sect> D&eacute;boguer et optimiser

<sect1> Etude pr&eacute;ventive du code (lint)
<label id="index.58"> <!-- lint -->

<p> Il n'existe pas de lint qui soit r&eacute;ellement utilisable, tout simplement
parce que la grande majorit&eacute; des d&eacute;veloppeurs sont satisfaits des messages
d'avertissement de gcc. Il est probable que l'option la plus utile est
l'option <tt/-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 &agrave; l'adresse suivante : <url
url="ftp://larch.lcs.mit.edu/pub/Larch/lclint">.  Je ne sais pas
ce qu'elle vaut.

<sect1> D&eacute;boguer
<label id="index.59"> <!-- debugging -->

<sect2> Comment rendre d&eacute;bogable un programme ?
<label id="index.60"> <!-- <tt/gcc -g/ -->
<label id="index.61"> <!-- <tt/gcc -fomit-frame-pointer/ -->
<label id="index.62"> <!-- <tt/libg.a/ -->

<p> Vous devez compiler et effectuer l'&eacute;dition de liens avec l'option
<tt/-g/, et sans l'option <tt/-fomit-frame-pointer/.  
En fait, vous ne devez compiler que les modules que 
vous avez besoin de d&eacute;boguer.

<p> Si vous poss&eacute;dez un syst&egrave;me a.out, les biblioth&egrave;ques dynamiques sont
compil&eacute;es avec l'option <tt/-fomit-frame-pointer/,
que gcc ne peut pas g&eacute;rer. Lorsque vous compilez avec l'option 
<tt/-g/, alors par d&eacute;faut vous effectuez une &eacute;dition de liens statique, ce
qui permet de r&eacute;soudre le probl&egrave;me.

<p> Si l'&eacute;diteur de liens &eacute;choue avec un message disant qu'il n'arrive
pas &agrave; trouver la biblioth&egrave;que libg.a, c'est que vous ne poss&eacute;dez pas
la biblioth&egrave;que <tt>/usr/lib/libg.a</tt>, qui est la biblioth&egrave;que C standard
permettant le d&eacute;bogage. Cette biblioth&egrave;que est fournie dans 
le paquetage des binaires de la libc., ou (dans les nouvelles versions)
vous aurez besoin de r&eacute;cup&eacute;rer le source et de le compiler vous-m&ecirc;me.
Vous n'avez pas r&eacute;ellement besoin de cela en fait, vous pouvez faire
un lien logique vers <tt>/usr/lib/libc.a</tt>

<sect3>Comment r&eacute;duire la taille des ex&eacute;cutables ?
<label id="index.63"> <!-- binaries too big -->

<p> Bon nombre de produits GNU sont fournis pour compiler avec l'option
<tt/-g/, ce qui g&eacute;n&egrave;re des ex&eacute;cutables d'une taille tr&egrave;s importante (et 
souvent l'&eacute;dition de liens s'effectue d'une mani&egrave;re statique).
Ce n'est pas une id&eacute;e lumineuse...

<p> Si le programme poss&egrave;de le script <tt/configure/ g&eacute;n&eacute;r&eacute; par
autoconf, vous pouvez modifier les options de d&eacute;bogage en 
effectuant un
<tt>./configure CFLAGS=</tt> ou <tt>./configure CFLAGS=-O2</tt>.  Sinon,
vous pouvez aller modifier le Makefile. Bien s&ucirc;r, si vous utilisez le format
ELF, l'&eacute;dition de liens sera effectu&eacute;e de mani&egrave;re dynamique m&ecirc;me avec l'option
<tt/-g/. Dans ce cas, vous pouvez effectuer un strip sur l'ex&eacute;cutable.

<sect2> Programmes disponibles
<label id="index.64"> <!-- gdb -->

<p> Beaucoup de gens utilisent <bf/gdb/, que vous pouvez r&eacute;cup&eacute;rer 
sur le site 
<url url="ftp://prep.ai.mit.edu/pub/gnu" name="prep.ai.mit.edu">, 
sous une forme binaire sur <url
url="ftp://tsx-11.mit.edu/pub/linux/packages/GCC" name="tsx-11"> ou
sur sunsite.  <bf/xxgdb/ est une surcouche X de gdb (c.a.d. que vous
avez besoin de gdb pour utiliser xxgdb). Les sources peuvent &ecirc;tre r&eacute;cup&eacute;r&eacute;s
sur <url
url="ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz">

Il existe &eacute;galement le d&eacute;bogueur <bf/UPS/ qui a &eacute;t&eacute; port&eacute; par Rick Sladkey. 
Il fonctionne sous X &eacute;galement, mais &agrave; la diff&eacute;rence d'xxgdb, ce n'est
qu'une surcouche X pour un d&eacute;bogueur en mode en texte. Il poss&egrave;de 
certaines caract&eacute;ristiques tr&egrave;s int&eacute;ressantes et si vous utilisez beaucoup
ce genre d'outils, vous l'essayerez s&ucirc;rement. Les patches ainsi que 
des versions pr&eacute;compil&eacute;es pour Linux peuvent &ecirc;tre trouv&eacute;es sur 
<url
url="ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/">, et les sources
peuvent &ecirc;tre r&eacute;cup&eacute;r&eacute;s sur <url
url="ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z">.

Un autre outil que vous pouvez trouver utile pour d&eacute;boguer est
« <bf/strace/ » , qui affiche les appels syst&egrave;mes que le processus
lance. Il poss&egrave;de d'autres caract&eacute;ristiques telles que donner les chemins
d'acc&egrave;s o&ugrave; ont &eacute;t&eacute; compil&eacute;s les binaires, donner les temps
pass&eacute;s dans chacun des appels syst&egrave;mes, et il vous permet &eacute;galement de
conna&icirc;tre les r&eacute;sultats des appels. La derni&egrave;re version de strace 
(actuellement la version 3.0.8) peut &ecirc;tre trouv&eacute;e sur 
<url url="ftp://ftp.std.com/pub/jrs/">.

<sect2> Programmes en t&acirc;che de fond (d&eacute;mon) 

<p> Les d&eacute;mons lancent typiquement un <tt/fork()/ d&egrave;s leur lancement et
terminent donc le p&egrave;re. Cela fait une session de d&eacute;boguage tr&egrave;s courte.

<p> La mani&egrave;re la plus simple de r&eacute;soudre ce probl&egrave;me est de poser
un point d'arr&ecirc;t sur <tt/fork/, et
lorsque le programme s'arr&ecirc;te, forcer le retour &agrave; 0.

<tscreen><verb>
(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       }
</verb></tscreen>

<sect2> Fichiers core

<p> Lorsque Linux se lance, il n'est g&eacute;n&eacute;ralement pas configur&eacute;
pour produire des fichiers core. Si vous les voulez vous devez utiliser
votre shell pour &ccedil;a en faisant sous csh (ou tcsh) :
<tscreen><verb>
% limit core unlimited
</verb></tscreen>
avec sh, bash, zsh, pdksh, utilisez
<tscreen><verb>
$ ulimit -c unlimited
</verb></tscreen>


Si vous voulez pousser le vice &agrave; nommer votre fichier core (par exemple
si vous utilisez un d&eacute;bogueur bogu&eacute;... ce qui est un comble) 
vous pouvez simplement modifier
le noyau. Editez les fichiers <tt>fs/binfmt_aout.c</tt> et
<tt>fs/binfmt_elf.c</tt> (dans les nouveaux noyaux, vous devrez 
chercher ailleurs) :

<tscreen><verb>
        memcpy(corefile,"core.",5);
#if 0
        memcpy(corefile+5,current->comm,sizeof(current->comm));
#else
        corefile[4] = '\0';
#endif
</verb></tscreen>

et changez les <tt/0/ par des <tt/1/.

<sect1>Caract&eacute;ristiques du programme

<p>Il est possible d'examiner un peu le programme pour 
savoir quels sont les appels de fonctions qui sont effectu&eacute;s le 
plus souvent ou bien qui prennent du temps. C'est une bonne mani&egrave;re
d'optimiser le code en d&eacute;terminant l&agrave; o&ugrave; l'on passe le plus de temps.
Vous devez compiler tous les objets avec l'option <tt/-p/, 
et pour mettre en forme la sortie &eacute;cran, vous aurez besoin du
programme <tt/gprof/ (situ&eacute; dans les <tt>binutils</tt>).  
Consultez les pages de manuel <tt/gprof/ pour plus de d&eacute;tails.

<sect>Edition de liens

<p> Entre les deux formats de binaires incompatibles, 
biblioth&egrave;ques statiques et dynamiques, on peut comparer l'op&eacute;ration
d'&eacute;dition de lien en fait &agrave; 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...

<p> Pour dissiper la confusion qui r&egrave;gne, nous allons nous baser sur
ce qui se passe lors d'ex&eacute;cution d'un programme, avec le chargement
dynamique. Vous verrez &eacute;galement la description de l'&eacute;dition
de liens dynamiques, mais plus tard. Cette section est
d&eacute;di&eacute;e &agrave; l'&eacute;dition de liens qui intervient &agrave; la fin de la compilation.

<sect1> Biblioth&egrave;ques partag&eacute;es contre biblioth&egrave;ques statiques

<p> La derni&egrave;re phase de construction d'un programme est de r&eacute;aliser
l'&eacute;dition de liens, ce qui consiste &agrave; assembler tous les morceaux 
du programme et de chercher ceux qui sont manquants. Bien &eacute;videment,
beaucoup de programmes r&eacute;alisent les m&ecirc;mes op&eacute;rations comme 
ouvrir des fichiers par exemple, et ces pi&egrave;ces qui r&eacute;alisent ce genre
d'op&eacute;rations sont fournies sous la forme de biblioth&egrave;ques. Sous Linux,
ces biblioth&egrave;ques peuvent &ecirc;tre trouv&eacute;es dans les r&eacute;pertoires 
<tt>/lib</tt> et<tt>/usr/lib/</tt> entre autres.

<label id="index.65"> <!-- binaries too big -->
<label id="index.66"> <!-- statically linked binaries, unexpected -->

Lorsque vous utilisez une biblioth&egrave;que statique, l'&eacute;diteur de liens
cherche le code dont votre programme a besoin et en effectue
une copie dans le programme physique g&eacute;n&eacute;r&eacute;. Pour les biblioth&egrave;ques
partag&eacute;es, c'est le contraire : l'&eacute;diteur de liens laisse du code
qui lors du lancement du programme chargera automatiquement la 
biblioth&egrave;que. Il est &eacute;vident que ces biblioth&egrave;ques permettent
d'obtenir un ex&eacute;cutable plus petit; elles permettent &eacute;galement
d'utiliser moins de m&eacute;moire et moins de place disque. Linux
effectue par d&eacute;faut une &eacute;dition de liens dynamique s'il peut trouver
les biblioth&egrave;ques de ce type sinon, il effectue une &eacute;dition de liens
statique. Si vous obtenez des binaires statiques alors que vous les 
voulez dynamiques v&eacute;rifiez que les biblioth&egrave;ques existent 
(<tt/*.sa/ pour le format a.out, et <tt/*.so/ pour le format ELF) et 
que vous poss&eacute;dez les droits suffisants pour y acc&eacute;der (lecture).

Sous Linux, les biblioth&egrave;ques statiques ont pour nom <tt/libnom.a/, 
alors que les biblioth&egrave;ques dynamiques sont appel&eacute;es 
<tt/libnnom.so.x.y.z/ o&ugrave; <tt/x.y.z/ repr&eacute;sente le num&eacute;ro de 
version. Les biblioth&egrave;ques dynamiques ont souvent des liens logiques qui
pointent dessus, et qui sont tr&egrave;s importants. Normalement, les biblioth&egrave;ques
standards sont livr&eacute;es sous la double forme dynamique
et statique.

Vous pouvez savoir de quelles biblioth&egrave;ques dynamiques un programme a besoin
en utilisant la commande <tt/ldd/ (<em>List Dynamic Dependencies</em>)
<tscreen><verb>
$ ldd /usr/bin/lynx
        libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
        libc.so.5 => /lib/libc.so.5.2.18
</verb></tscreen>

Cela indique sur mon syst&egrave;me que l'outil <tt>lynx</tt> (outil WWW) 
a besoin des biblioth&egrave;ques dynamiques <tt/libc.so.5/ (la biblioth&egrave;que C)
et de <tt/libncurses.so.1/ (n&eacute;cessaire pour le contr&ocirc;le du terminal). 
Si un programme ne poss&egrave;de pas de d&eacute;pendances, <tt/ldd/ indiquera
`<em/statically linked/' (&eacute;dition de liens statique).

<sect1>A la recherche des fonctions... ou dans quelle biblioth&egrave;que se trouve 
la fonction <tt/sin()/ ?')
<label id="index.67"> <!-- <tt/sin()/ -->
<label id="index.68"> <!-- <tt/cos()/ -->
<label id="index.69"> <!-- maths -->

<p> <tt/nm /<em/nomdebiblioth&egrave;que/ vous donne tous les symboles r&eacute;f&eacute;renc&eacute;s dans
la biblioth&egrave;que. Cela fonctionne que cela soit du code statique ou dynamique.
Supposez que vous vouliez savoir o&ugrave; se trouve d&eacute;finie la fonction
<tt/tcgetattr()/ :
<tscreen><verb>
$ nm libncurses.so.1 |grep tcget
         U tcgetattr
</verb></tscreen>

La lettre <tt/U/ vous indique que c'est ind&eacute;fini (<em>Undefined</em>)
--- cela indique que la biblioth&egrave;que ncurses l'utilise mais ne la d&eacute;finit pas.
Vous pouvez &eacute;galement faire :

<tscreen><verb>
$ nm libc.so.5 | grep tcget
00010fe8 T __tcgetattr
00010fe8 W tcgetattr
00068718 T tcgetpgrp
</verb></tscreen>

La lettre `<tt/W/' indique que le symbole est d&eacute;fini mais de telle
mani&egrave;re qu'il peut &ecirc;tre surcharg&eacute; par une autre d&eacute;finition de la fonction
dans une autre biblioth&egrave;que (W pour <em>weak</em> : faible).
Une d&eacute;finition normale est marqu&eacute;e par la lettre `<tt/T/' 
(comme pour <tt/tcgetpgrp/).

<label id="index.70"> <!-- <tt/&lt;math.h&gt;/ -->

La r&eacute;ponse &agrave; la question situ&eacute;e dans le titre est 
<tt/libm.(so|a)/.  Toutes les fonctions d&eacute;finies dans le fichier
d'en-t&ecirc;te <tt>&lt;math.h&gt;</tt> sont impl&eacute;ment&eacute;es dans la
biblioth&egrave;que math&eacute;matique donc vous devrez effectuer l'&eacute;dition de liens
gr&acirc;ce &agrave; <tt/-lm/.

<!-- 13) Why are my binaries so huge and how do I reduce them ? -->
<!-- covered static/shared, need to look at -g, -N -->

<sect1>Trouver les fichiers<p>

Supposons que vous ayez le message d'erreur suivant de la part
de l'&eacute;diteur de liens :
<p><tt/ld: Output file requires shared library `libfoo.so.1`/

<p> La strat&eacute;gie de recherche de fichiers de ld ou de ses copains
diff&egrave;re de la version utilis&eacute;e, mais vous pouvez &ecirc;tre s&ucirc;r 
que les fichiers situ&eacute;s dans le r&eacute;pertoire <tt>/usr/lib</tt> 
seront trouv&eacute;s. Si vous d&eacute;sirez que des fichiers situ&eacute;s &agrave; un endroit
diff&eacute;rent soient trouv&eacute;s, il est pr&eacute;f&eacute;rable d'ajouter l'option
<tt/-L/ &agrave; gcc ou ld.

<p> Si cela ne vous aide pas clairement, v&eacute;rifiez que vous avez le bon
fichier &agrave; l'endroit sp&eacute;cifi&eacute;. Pour un syst&egrave;me a.out,
effectuer l'&eacute;dition de liens avec <tt/-ltruc/ implique que ld recherche
les biblioth&egrave;ques  <tt/libtruc.sa/ (biblioth&egrave;ques partag&eacute;es), et si elle
n'existe pas, il recherche <tt/libtruc.a/ (statique).  Pour le format
ELF, il cherche <tt/libtruc.so/ puis <tt/libtruc.a/.  
<tt/libtruc.so/ est g&eacute;n&eacute;ralement un lien symbolique vers
<tt/libtruc.so.x/.

<sect1> Compiler votre propre biblioth&egrave;que

<sect2> Num&eacute;ro de la version

<p> Comme tout programme, les biblioth&egrave;ques ont tendance &agrave; avoir quelques
bogues qui sont corrig&eacute;s au fur et &agrave; mesure. De nouvelles 
fonctionnalit&eacute;s sont ajout&eacute;es et qui peuvent changer l'effet
de celles qui existent ou bien certaines anciennes peuvent &ecirc;tres supprim&eacute;es.
Cela peut &ecirc;tre un probl&egrave;me pour les programmes qui les utilisent.

Donc, nous introduisons la notion de num&eacute;ro de version. Nous
r&eacute;pertorions les modifications effectu&eacute;es dans la biblioth&egrave;ques
comme &eacute;tant soit mineures soit majeures. Cela signifie qu'une 
modification mineure ne peut pas modifier le fonctionnement d'un
programme (en bref, il continue &agrave; fonctionner comme avant). Vous pouvez
identifier le num&eacute;ro de la version de la biblioth&egrave;que en regardant
son nom (en fait c'est un mensonge pour les biblioth&egrave;ques ELF... mais
continuez &agrave; faire comme si !) : <tt/libtruc.so.1.2/ a pour version
majeure 1 et mineure 2.  Le num&eacute;ro de version mineur peut &ecirc;tre
plus ou moins &eacute;lev&eacute; --- la biblioth&egrave;que C met un num&eacute;ro de patch,
ce qui produit un nom tel que <tt/libc.so.5.2.18/, et c'est &eacute;galement
courant d'y trouver des lettres ou des blancs soulign&eacute;s ou tout
autre caract&egrave;re ASCII affichable.

Une des principales diff&eacute;rences entre les formats ELF et a.out
se trouve dans la mani&egrave;re de construire la biblioth&egrave;que partag&eacute;e.
Nous traiterons les biblioth&egrave;ques partag&eacute;es en premier car c'est plus
simple.

<sect2> ELF, qu'est-ce que c'est ?
<label id="index.71"> <!-- elf -->

<p> ELF (<em>Executable and Linking Format</em>) est format de binaire
initialement con&ccedil;u et d&eacute;velopp&eacute; par USL (<em>UNIX System Laboratories</em>)
et utilis&eacute; dans les syst&egrave;mes Solaris et System R4. En raison de sa
facilit&eacute; d'utilisation par rapport &agrave; l'ancien format dit a.out qu'utilisait
Linux, les d&eacute;veloppeurs de GCC et de la biblioth&egrave;que C ont d&eacute;cid&eacute; 
l'ann&eacute;e derni&egrave;re de basculer tout le syst&egrave;me sous le format ELF. ELF
est d&eacute;sormais le format binaire standard sous Linux.

<sect3> ELF, le retour !

<p> Ce paragraphe provient du groupe '/news-archives/comp.sys.sun.misc'.

<quote>
ELF (<em>Executable Linking Format</em>) 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 o&ugrave; il
est extensible. ELF voit un fichier objet comme une longue
liste de sections (plut&ocirc;t qu'un tableau de taille fixe 
d'&eacute;l&eacute;ments). Ces sections, &agrave; la diff&eacute;rence de COFF ne se trouvent
pas &agrave; un endroit constant et ne sont pas dans un ordre
particulier, etc. Les utilisateurs peuvent ajouter une nouvelle
section &agrave; ces fichiers objets s'il d&eacute;sirent y mettre de nouvelles
donn&eacute;es. ELS poss&egrave;de un format de d&eacute;bogage plus puissant
appel&eacute; DWARF (<em>Debugging With Attribute Record Format</em>) - 
par encore enti&egrave;rement g&eacute;r&eacute; par Linux (mais on y travaille !). 
Une liste cha&icirc;n&eacute;e de « DWARF DIEs » (ou <em>Debugging Information 
Entries</em> - NdT... le lecteur aura s&ucirc;rement not&eacute; le jeu de mot
assez noir : dwarf = nain; dies = morts) forment la section <em>.debug</em>
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 &eacute;crits sous la forme d'un arbre de donn&eacute;es.
Les DIEs peuvent contenir une plus grande quantit&eacute; d'information
que la section <em>.debug</em> du format COFF ne le pouvait (un peu comme
les graphes d'h&eacute;ritages du C++).
</quote>
<quote>
Les fichiers ELF sont accessibles gr&acirc;ce &agrave; la biblioth&egrave;que d'acc&egrave;s 
de SVR4 (Solaris 2.0 peut-&ecirc;tre ?), qui fournit une interface simple
et rapide aux parties les plus complexes d'ELF. Une des aubaines que
permet la biblioth&egrave;que d'acc&egrave;s ELF est que vous n'avez jamais besoin
de conna&icirc;tre les m&eacute;andres du format ELF. Pour acc&eacute;der &agrave; un fichier Unix,
on utilise un Elf *, retourn&eacute; par un appel &agrave; elf_open(). Ensuite,
vous effectuez des appels &agrave; elf_foobar() pour obtenir les diff&eacute;rents
composants au lieu d'avoir &agrave; triturer le fichier physique 
sur le disque (chose que beaucoup d'utilisateurs de COFF ont fait...).
</quote>

Les arguments pour ou contre ELF, et les probl&egrave;mes li&eacute;s
&agrave; la mise &agrave; jour d'un syst&egrave;me a.out vers un syst&egrave;me ELF sont d&eacute;crits 
dans le ELF-HOWTO et je ne veux pas effectuer de copier coller ici
(NdT: ce HowTo est &eacute;galement traduit en fran&ccedil;ais).
Ce HowTo se trouve au m&ecirc;me endroit que les autres.

<sect3> Les biblioth&egrave;que partag&eacute;es ELF

<p> Pour construire <tt/libtruc.so/ comme une biblioth&egrave;que dynamique,
il suffit de suivre les &eacute;tapes suivantes :

<tscreen><verb>
$ 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
</verb></tscreen>

Cela va g&eacute;n&eacute;rer une biblioth&egrave;que partag&eacute;e appel&eacute;e <tt>libtruc.so.1.0</tt>, 
les liens appropri&eacute;s pour ld (<tt>libtruc.so</tt>) et 
le chargeur dynamique (<tt>libtruc.so.1</tt>) pour le trouver. 
Pour tester, nous ajoutons le r&eacute;pertoire actuel &agrave; la 
variable d'environnement <tt/LD_LIBRARY_PATH/.

<label id="index.72"> <!-- weird things -->

Lorsque vous &ecirc;tes satisfait et que la biblioth&egrave;que fonctionne, vous
n'avez plus qu'&agrave; la d&eacute;placer dans le r&eacute;pertoire par exemple, 
<tt>/usr/local/lib</tt>, et de recr&eacute;er les liens appropri&eacute;s. Le lien
de <tt/libtruc.so.1/ sur <tt/libtruc.so.1.0/ est enregistr&eacute; par 
<tt>ldconfig</tt>, qui sur bon nombre de syst&egrave;mes est lanc&eacute; lors 
du processus d'amor&ccedil;age. Le lien <tt>libfoo.so</tt> doit &ecirc;tre mis &agrave; jour
&agrave; la main. Si vous faites attention lors de la mise &agrave; jour de la
biblioth&egrave;que la chose la plus simple &agrave; r&eacute;aliser est de cr&eacute;er le lien
<tt>libfoo.so -> libfoo.so.1</tt>, pour que ldconfig conserve les liens
actuels. Si vous ne faites pas cela, vous aurez des probl&egrave;mes plus
tard. Ne me dites pas que l'on ne vous a pas pr&eacute;venu !

<tscreen><verb>
$ /bin/su
# cp libtruc.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libtruc.so.1 libtruc.so )
</verb></tscreen>

<sect3> Les num&eacute;ros de version, les noms et les liens
<label id="index.73"> <!-- soname -->
<label id="index.74"> <!-- version numbers -->

<p> Chaque biblioth&egrave;que poss&egrave;de un nom propre (<em>soname</em>).  
Lorsque l'&eacute;diteur de liens en trouve un qui correspond &agrave; un nom
cherch&eacute;, il enregistre le nom de la biblioth&egrave;que dans le code binaire
au lieu d'y mettre le nom du fichier de la biblioth&egrave;que. Lors de
l'ex&eacute;cution, le chargeur dynamique va alors chercher un fichier ayant
pour nom le nom propre de la biblioth&egrave;que, et pas le nom du fichier
de la biblioth&egrave;que. Par exemple, une biblioth&egrave;que ayant pour nom
<tt/libtruc.so/ peut avoir comme nom propre <tt/libbar.so/, et tous
les programmes li&eacute;s avec vont alors chercher <tt/libbar.so/ 
lors de leur ex&eacute;cution.

<p>Cela semble &ecirc;tre une nuance un peu pointilleuse mais c'est la clef
de la compr&eacute;hension de la coexistence de plusieurs versions
diff&eacute;rentes de la m&ecirc;me biblioth&egrave;que sur le m&ecirc;me syst&egrave;me.
On a pour habitude sous Linux d'appeler une biblioth&egrave;que 
<tt>libtruc.so.1.2</tt> par exemple, et de lui donner comme
nom propre <tt>libtruc.so.1</tt>.  Si cette biblioth&egrave;que est rajout&eacute;e
dans un r&eacute;pertoire standard (par exemple dans <tt>/usr/lib</tt>), 
le programme <tt>ldconfig</tt> va cr&eacute;er un lien symbolique
entre <tt>libtruc.so.1 -> libtruc.so.1.2</tt> pour que l'image
appropri&eacute;e soit trouv&eacute;e lors de l'ex&eacute;cution. Vous aurez &eacute;galement besoin
d'un lien symbolique  <tt>libtruc.so -> libtruc.so.1</tt> pour que ld
trouve le nom propre lors de l'&eacute;dition de liens.</p>

<p> Donc, lorsque vous corrigez des erreurs dans la biblioth&egrave;que ou
bien lorsque vous ajoutez de nouvelles fonctions (en fait, pour
toute modification qui n'affecte pas l'ex&eacute;cution des programmes d&eacute;j&agrave;
existants), vous reconstruisez la biblioth&egrave;que, conservez le nom propre
tel qu'il &eacute;tait et changez le nom du fichier. Lorsque vous effectuez des 
modifications que peuvent modifier le d&eacute;roulement des programmes
existants, vous pouvez tout simplement incr&eacute;menter le nombre situ&eacute; 
dans le nom propre --- dans ce cas, appelez la nouvelle version de la
biblioth&egrave;que <tt>libtruc.so.2.0</tt>, et donnez-lui comme nom propre
<tt>libtruc.so.2</tt>.  Maintenant, faites pointer le lien de 
<tt>libfoo.so</tt> vers la nouvelle version et tout est bien dans
le meilleur des mondes !

Il est utile de remarquer que vous n'&ecirc;tes pas oblig&eacute; de nommer 
les biblioth&egrave;ques de cette mani&egrave;re, mais c'est une bonne convention.
Elf vous donne une certaine libert&eacute; pour nommer des biblioth&egrave;ques
tant et si bien que cela peut perturber certains utilisateurs, mais cela
ne veut pas dire que vous &ecirc;tes oblig&eacute; de le faire.

R&eacute;sum&eacute; : supposons que choisissiez d'adopter la m&eacute;thode traditionnelle
avec les mises &agrave; jour majeures qui peuvent ne pas &ecirc;tre compatibles
avec les versions pr&eacute;c&eacute;dentes et les mises &agrave; jour mineures qui ne posent
pas ce probl&egrave;me. Il suffit de cr&eacute;er la biblioth&egrave;que de cette mani&egrave;re :

<tscreen><verb>
gcc -shared -Wl,-soname,libtruc.so.majeur -o libtruc.so.majeur.mineur
</verb></tscreen>
et tout devrait &ecirc;tre parfait !

<sect2> a.out.  Le bon vieux format 

<p> La facilit&eacute; de construire des biblioth&egrave;que partag&eacute;es est la 
raison principale de passer &agrave; ELF. Ceci dit, il est toujours possible
de cr&eacute;er des biblioth&egrave;ques dynamiques au format a.out. R&eacute;cup&eacute;rez 
le fichier archive 
<url url=
"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
apr&egrave;s l'avoir d&eacute;sarchiv&eacute;. Je n'aime pas avoir l'air d'&ecirc;tre aussi
partisan, mais il est clair que je n'ai jamais aim&eacute; ce format :-).

<sect3> ZMAGIC contre QMAGIC
<label id="index.75"> <!-- ZMAGIC -->
<label id="index.76"> <!-- QMAGIC -->

<p> QMAGIC est le format des ex&eacute;cutables qui ressemble un peu aux vieux
binaires a.out (&eacute;galement connu comme ZMAGIC), mais qui laisse
la premi&egrave;re page libre. Cela permet plus facilement de r&eacute;cup&eacute;rer
les adresses non affect&eacute;es (comme NULL) dans l'intervalle
0-4096 (NdT : Linux utilise des pages de 4Ko).

Les &eacute;diteurs de liens d&eacute;suets ne g&egrave;rent que le format ZMAGIC, ceux
un peu moins rustiques g&egrave;rent les deux, et les plus r&eacute;cents uniquement
le QMAGIC. Cela importe peu car le noyau g&egrave;re les deux types.

La commande <tt>file</tt> est capable d'identifier si un programme est
de type QMAGIC.

<sect3>Gestion des fichiers

<p>Une biblioth&egrave;que dynamique a.out (DLL) est compos&eacute;e de 
deux fichiers et d'un lien symbolique. Supposons que l'on
utilise la biblioth&egrave;que <em>truc</em>, les fichiers seraient
les suivants : <tt/libtruc.sa/ et <tt/libtruc.so.1.2/; et le 
lien symbolique aurait pour nom <tt/libtruc.so.1/ et pointerait
sur le dernier des fichiers. Mais &agrave; quoi servent-ils ?

Lors de la compilation, <tt/ld/ cherche <tt/libtruc.sa/.  
C'est le fichier de description de la biblioth&egrave;que : il contient
toutes les donn&eacute;es export&eacute;es et les pointeurs vers les fonctions
n&eacute;cessaires pour l'&eacute;dition de liens.

Lors de l'ex&eacute;cution, le chargeur dynamique cherche <tt/libtruc.so.1/.
C'est un lien symbolique plut&ocirc;t qu'un r&eacute;el fichier pour que les
biblioth&egrave;ques puissent &ecirc;tre mise &agrave; jour sans avoir &agrave; casser les
applications qui utilisent la biblioth&egrave;que. Apr&egrave;s la mise &agrave; jour, 
disons que l'on est pass&eacute; &agrave; la version <tt/libfoo.so.1.3/,
le lancement de ldconfig va positionner le lien. Comme 
cette op&eacute;ration est atomique, aucune application fonctionnant 
n'aura de probl&egrave;me.

Les biblioth&egrave;ques DLL (Je sais que c'est une tautologie... mais pardon !) 
semblent &ecirc;tre tr&egrave;s souvent plus importantes que leur &eacute;quivalent
statique. En fait, c'est qu'elles r&eacute;servent de la place pour les
extensions ult&eacute;rieures sous la simple forme de trous qui sont
fait de telle mani&egrave;re qu'ils n'occupent pas de place disque (NdT : 
un peu comme les fichiers <tt>core</tt>). Toutefois, un
simple appel &agrave; <tt/cp/ ou &agrave; <tt/makehole/ les remplira...
Vous pouvez effectuer une op&eacute;ration de <tt>strip</tt> apr&egrave;s la construction
de la biblioth&egrave;que, comme les adresses sont &agrave; des endroits fixes.
<bf>Ne faites pas la m&ecirc;me op&eacute;ration avec les biblioth&egrave;ques ELF !</bf>

<sect3> « libc-lite » ?

<p> Une « libc-lite » (contraction de <em>libc</em> et <em>little</em>)
est une version &eacute;pur&eacute;e et r&eacute;duite de la biblioth&egrave;que 
libc construite de telle mani&egrave;re qu'elle puisse tenir sur 
une disquette avec un certain nombre d'outil Unix.
Elle n'inclut pas curses, dbm, termcap, ... 
Si votre <tt>/lib/libc.so.4</tt> est li&eacute;e avec une biblioth&egrave;que de ce genre
il est tr&egrave;s fortement conseill&eacute; de la remplacer avec une version compl&egrave;te.

<sect2> Edition de liens : probl&egrave;me courants 

<p> Envoyez-les moi ! 

<descrip>

<tag> Des programmes statiques lorsque vous les voulez
partag&eacute;s</tag>
<label id="index.77"> <!-- binaries too big -->
<label id="index.78"> <!-- statically linked binaries, unexpected -->

V&eacute;rifiez que vous avez les bons liens pour que <tt/ld/ puisse
trouver les biblioth&egrave;ques partag&eacute;es. Pour ELF cela veut dire que
<tt>libtruc.so</tt> est un lien symbolique sur son image,
pour a.out un fichier <tt>libtruc.sa</tt>.  Beaucoup de personnes
ont eu ce probl&egrave;me apr&egrave;s &ecirc;tre pass&eacute;s des outils ELF 2.5 &agrave; 2.6 
(<tt>binutils</tt>) --- la derni&egrave;re version effectue une recherche
plus intelligente pour les biblioth&egrave;ques dynamiques et donc ils 
n'avaient pas cr&eacute;&eacute; tous les liens symboliques n&eacute;cessaires.
Cette caract&eacute;ristique avait &eacute;t&eacute; supprim&eacute;e pour des raisons de compatibilit&eacute;
avec d'autres architectures et parce qu'assez souvent cela ne marchait
pas bien. En bref, cela posait plus de probl&egrave;mes qu'autre chose.

<tag> Le programme `mkimage' n'arrive pas &agrave; trouver libgcc</tag> 
<label id="index.79"> <!-- libgcc -->

	Comme <tt/libc.so.4.5.x/ et suivantes, libgcc n'est pas une 
biblioth&egrave;que partag&eacute;e. Vous devez remplacer les `<tt/-lgcc/' 
sur la ligne de commande par 
<tt/`gcc -print-libgcc-file-name`/ (entre quotes)

Egalement, d&eacute;truisez tous les fichiers situ&eacute;s dans <tt>/usr/lib/libgcc*</tt>.
C'est important.

<tag> Le message <tt>__NEEDS_SHRLIB_libc_4 multiply defined</tt></tag> 

Sont une cons&eacute;quence du m&ecirc;me probl&egrave;me.

<tag> Le message ``Assertion failure'' appara&icirc;t lorsque vous reconstruisez une
DLL</tag>

Ce message &eacute;nigmatique signifie qu'un &eacute;l&eacute;ment de votre table <em>jump</em>
a d&eacute;pass&eacute; la table car trop peu de place &eacute;tait r&eacute;serv&eacute;e dans le fichier 
<tt/jump.vars/ file.  Vous pouvez trouver le(s) coupable(s) en lan&ccedil;ant 
la commande <tt/getsize/ fournie dans le paquetage tools-2.17.tar.gz. 
La seule solution est de passer &agrave; une nouvelle version majeure,
m&ecirc;me si elle sera incompatible avec les pr&eacute;c&eacute;dentes.

<tag> <tt/ld: output file needs shared library libc.so.4/ </tag>

Cela arrive lorsque vous effectuez l'&eacute;dition de liens avec des biblioth&egrave;ques
diff&eacute;rentes de la libc (comme les biblioth&egrave;ques X) et que vous utilisez
l'option <tt/-g/ sans utiliser l'option <tt/-static/.

Les fichiers <tt/.sa/ pour les biblioth&egrave;ques dynamiques ont un symbole
non r&eacute;solu <tt/_NEEDS_SHRLIB_libc_4/ qui est d&eacute;fini dans 
<tt/libc.sa/.  Or, lorsque vous utilisez <tt/-g/ vous faites l'&eacute;dition
de liens avec <tt/libg.a/ ou <tt/libc.a/ et donc ce symbole n'est jamais 
d&eacute;fini.

Donc, pour r&eacute;soudre le probl&egrave;me, ajoutez l'option <tt/-static/ 
lorsque vous compilez avec l'option <tt/-g/, ou n'utilisez pas
<tt/-g/ lors de l'&eacute;dition de liens !
</descrip>


<sect>Chargement dynamique

<p> <em>Ce paragraphe est en fait un peu court : il sera
&eacute;tendu dans une version ult&eacute;rieure d&egrave;s que j'aurai r&eacute;cup&eacute;r&eacute; le 
HowTo ELF</em>

<sect1>Concepts

<p> Linux poss&egrave;de des biblioth&egrave;ques dynamiques, comme on vous le 
r&eacute;p&egrave;te depuis le d&eacute;but de ce document ! Or, il existe un syst&egrave;me
pour reporter le travail d'association des noms des symboles et de
leur adresse dans la biblioth&egrave;que, qui est normalement effectu&eacute; lors de 
l'&eacute;dition de liens en l'effectuant lors du chargement du programme.

<sect1> Messages d'erreur

<p> Envoyez moi vos erreurs !  Je n'en fait pas grand chose sauf les ins&eacute;rer 
dans ce paragraphe...

<descrip>

<tag> <tt>can't load library: /lib/libxxx.so, Incompatible version</tt></tag>

(seulement a.out) Cela signifie que vous n'avez pas la version correcte
de la biblioth&egrave;que (num&eacute;ro dit majeur). Non, il n'est pas possible
d'effectuer un lien symbolique sur la biblioth&egrave;que que vous poss&eacute;dez : si 
vous avez de la chance, vous obtiendrez un <em>segmentation fault</em>.  
R&eacute;cup&eacute;rez la nouvelle version.  Un message un peu &eacute;quivalent existe
&eacute;galement sur les syst&egrave;mes ELF :

<tscreen><verb>
ftp: can't load library 'libreadline.so.2'
</verb></tscreen>


<tag><tt/warning using incompatible library version xxx/</tag>

(seulement a.out) Vous avez un num&eacute;ro de version de biblioth&egrave;que (mineur)
inf&eacute;rieur &agrave; la version avec laquelle a &eacute;t&eacute; compil&eacute; le programme.
Le programme fonctionnera s&ucirc;rement. Une mise &agrave; jour est toutefois
conseill&eacute;e.

</descrip>

<sect1> Contr&ocirc;ler l'op&eacute;ration de chargement dynamique
<label id="index.80"> <!-- <tt/LD_*/ environment variables -->
<label id="index.81"> <!-- ldd -->

<p> Il existe certaines variables d'environnements que le chargeur dynamique
utilise. Beaucoup sont exploit&eacute;es par le programme <tt/ldd/ lorsqu'il
s'agit de particularit&eacute;s de l'environnement de l'utilisateur, ce qui
peuvent &ecirc;tre positionn&eacute;es pour lancer ldd avec des options
particuli&egrave;res. Voici une description des diff&eacute;rentes variables d'environnement
que vous pouvez rencontrer :

<itemize>

<item> <tt/LD_BIND_NOW/ --- normalement, les fonctions ne sont 
pas cherch&eacute;es dans les biblioth&egrave;ques avant leur appel. En positionnant 
cette option, vous v&eacute;rifiez que toutes les fonctions employ&eacute;es dans
votre programmes se trouvent bien dans la biblioth&egrave;que lors de son 
chargement, ce qui ralentit le lancement du programme. C'est utile lorsque
vous voulez tester que l'&eacute;dition de liens s'est parfaitement d&eacute;roul&eacute;e
et que tous les symboles sont bien associ&eacute;s.

<item> <tt/LD_PRELOAD/ peut &ecirc;tre d&eacute;fini avec un nom de fichier
qui contient des fonctions surchargeant des fonctions d&eacute;j&agrave; existantes.
Par exemple, si vous testez une strat&eacute;gie d'allocation m&eacute;moire,
et que vous voulez remplacer le malloc de la biblioth&egrave;que C par le 
v&ocirc;tre situ&eacute; dans un module ayant pour nom <tt/malloc.o/, il vous suffit
de faire :
<tscreen><verb>
$ export LD_PRELOAD=malloc.o
$ test_mon_malloc
</verb></tscreen>

<tt/LD_ELF_PRELOAD/ et <tt/LD_AOUT_PRELOAD/ sont similaires, mais 
leur utilisation est sp&eacute;cifique au type de binaire utilis&eacute;. Si
<tt/LD_/<em/TypeBinaire/<tt/_PRELOAD/ et <tt/LD_PRELOAD/ sont positionn&eacute;s,
celui correspondant le mieux &agrave; la machine est utilis&eacute;.

<item> <tt/LD_LIBRARY_PATH/ contient une liste de r&eacute;pertoires contenant
les biblioth&egrave;ques dynamiques. Cela n'affecte pas l'&eacute;dition de liens :
cela n'a qu'un effet lors de l'ex&eacute;cution. Il faut noter qu'elle est
d&eacute;sactiv&eacute;e pour des programmes qui s'ex&eacute;cutent avec un setuid ou un setgid.  
Enfin, <tt/LD_ELF_LIBRARY_PATH/ et 
<tt/LD_AOUT_LIBRARY_PATH/ peuvent &ecirc;tre utilis&eacute;s pour orienter le mode de
compilation du binaire.  <tt/LD_LIBRARY_PATH/
ne devrait pas &ecirc;tre n&eacute;cessaire en principe : ajoutez les r&eacute;pertoires dans le
fichier <tt>/etc/ld.so.conf/</tt> et relancez ldconfig.

<item> <tt/LD_NOWARN/ s'applique au format a.out uniquement.  Lorsqu'elle
est positionn&eacute;e (c.a.d si elle existe par exemple avec
<tt/LD_NOWARN=true; export LD_NOWARN/) cela arr&ecirc;te le chargeur du programme
m&ecirc;me sur des avertissements insignifiants (tels que des messages 
d'incompatibilit&eacute;s de num&eacute;ros mineurs de version).

<item> <tt/LD_WARN/ s'applique &agrave; ELF uniquement.  Lorsqu'elle est 
positionn&eacute;e, on transforme le message habituellement fatal <em>Can't find 
library</em> en un avertissement. Ce n'est pas positionn&eacute; par d&eacute;faut mais
c'est important pour un programme comme ldd.

<item> <tt/LD_TRACE_LOADED_OBJECTS/ s'applique &agrave; ELF uniquement, et
permet de simuler l'ex&eacute;cution des programmes comme s'ils l'&eacute;taient 
par <tt/ldd/ :

<tscreen><verb>
$ 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
</verb></tscreen>

</itemize>

<sect1> Ecrire des programmes en utilisant le chargement dynamique
<label id="index.82"> <!-- <tt/dlopen()/ -->
<label id="index.83"> <!-- <tt/dlsym()/ -->

<p> Cela ressemble &eacute;norm&eacute;ment au syst&egrave;me de chargement dynamique
utilis&eacute; sous Solaris 2.x. Ce syst&egrave;me est d&eacute;crit d'une 
mani&egrave;re pr&eacute;cise dans le document expliquant la programmation 
avec ELF &eacute;crit par H J Lu et dans la page de manuel
<tt>dlopen(3)</tt>, qui se trouve dans le paquetage ld.so. 
Voici un exemple simple : pensez &agrave; faire l'&eacute;dition de liens avec 
<tt>-ldl</tt>

<tscreen><verb>
#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");
  }

}
</verb></tscreen>

<sect> Contacter les d&eacute;veloppeurs

<sect1> Annoncer des bogues
<label id="index.84"> <!-- gcc, bugs -->

<p> Commencez par mettre en doute le probl&egrave;me. Est-ce sp&eacute;cifique &agrave; 
Linux ou bien cela arrive avec gcc mais sur d'autres plates-formes ?
Est-ce sp&eacute;cifique &agrave; la version du noyau ? A la version de la biblioth&egrave;que C ?
Est-ce que ce probl&egrave;me dispara&icirc;t lorsque vous effectuez une &eacute;dition de liens
statique ? Pouvez-vous produire un code tr&egrave;s court mettant en &eacute;vidence
le probl&egrave;me ?

Apr&egrave;s avoir r&eacute;pondu apr&egrave;s ces quelques questions, vous saurez
quel programme est &agrave; l'origine du probl&egrave;me. Pour un probl&egrave;me direct avec
GCC, le mieux est de consulter le fichier d'information livr&eacute; avec : la
proc&eacute;dure pour rapporter un bogue y est d&eacute;taill&eacute;. Pour un probl&egrave;me avec
ld.so, la biblioth&egrave;que C ou math&eacute;matique, envoyez un courrier &eacute;lectronique
&agrave; <tt/linux-gcc@vger.rutgers.edu/.  Si possible, donnez un court
exemple mettant en &eacute;vidence le probl&egrave;me ainsi qu'une courte description
indiquant ce que le programme aurait normalement d&ucirc; faire, et ce qu'il fait
en r&eacute;alit&eacute;.

<sect1> Participer au d&eacute;veloppement

<p> Si vous d&eacute;sirez participer au d&eacute;veloppement de GCC ou de la 
biblioth&egrave;que C, la premi&egrave;re chose &agrave; faire est de rejoindre
la liste de diffusion <tt/linux-gcc@vger.rutgers.edu/.  Si vous d&eacute;sirez
uniquement savoir de quoi &ccedil;a parle, il existe des archives &agrave;
l'adresse <url
url="http://homer.ncm.com/linux-gcc/">.  Tout d&eacute;pend de ce que vous
d&eacute;sirez faire ou apporter &agrave; ce projet !

<sect> Divers

<sect1> Ce document

<p> Ce HowTo est bas&eacute; sur la FAQ de Mitchum DSouza's. Bon nombre
des informations en proviennent. D'une mani&egrave;re g&eacute;n&eacute;rale, 
il est fr&eacute;quent de dire une phrase du genre « je n'ai pas tout test&eacute; et 
donc ne me bl&acirc;mez pas si vous cassez votre disque, votre syst&egrave;me
ou si vous rompez avec votre &eacute;pouse ».

Le nom des contributeurs &agrave; ce document sont donn&eacute;s par ordre alphab&eacute;tique :
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 s&ucirc;r Linus Torvalds, sans qui ce genre d'exercice aurait &eacute;t&eacute; 
difficile, voir impossible :-)

Ne soyez pas offens&eacute; si votre nom n'appara&icirc;t pas dans la liste et que 
vous ayez contribu&eacute; &agrave; ce document (sous la forme d'un HowTo ou d'une FAQ).
Envoyez-moi un courrier &eacute;lectronique et j'effectuerai la correction.

<sect1> Traduction

<p> A l'heure ou j'&eacute;cris ces lignes, je ne connais pas de traduction
de ce document. Si vous en r&eacute;alisez une, s'il vous pla&icirc;t dites-le moi.
Je suis disponible pour toute aide concernant l'explication du texte,
je serai tr&egrave;s content d'y r&eacute;pondre.

Note du traducteur : <bf>Cocorico !</bf> La version fran&ccedil;aise est
la premi&egrave;re traduction de ce document. 

<sect1> Contacts<p>

Tout contact est le bienvenu. Envoyez-moi un courrier &eacute;lectronique
&agrave; l'adresse suivante : <htmlurl
url="mailto:dan@detached.demon.co.uk"
name="dan@detached.demon.co.uk">.  Ma clef publique PGP (ID 5F263625) est
disponible sur mes <url url="http://ftp.linux.org.uk/~barlow/"
name="pages WWW">, Si vous souhaitez rendre confidentiel certains messages.

<sect1> Copyright

<p> Toutes les remarques appartiennent &agrave; leurs auteurs respectifs.

Ce document est copyright&eacute; (C) 1996 Daniel Barlow 
<tt/&lt;dan@detached.demon.co.uk&gt;/. Il peut &ecirc;tre reproduit et 
distribu&eacute; en partie ou enti&egrave;rement, sur tout support physique ou &eacute;lectronique,
du moment o&ugrave; ce copyright se trouve sur toute les copies. La redistribution
commerciale est autoris&eacute;e et encourag&eacute;e. Toutefois l'auteur de ce document
doit &ecirc;tre mis au courant de ce genre de distributions.

Toute traduction, adaptation, ou bien tout travail incorporant tout
document HowTo Linux doit poss&eacute;der ce copyright. De cette mani&egrave;re, vous
ne pouvez pas imposer de restriction &agrave; la distribution de ce document.
Des exceptions peuvent &ecirc;tre &eacute;ventuellement accord&eacute;es sous certaines
conditions : contactez le coordinateur des HowTo's Linux &agrave; l'adresse 
donn&eacute;e ci-dessous.

En r&eacute;sum&eacute;, nous souhaitons voir diffuser l'information de la mani&egrave;re
la plus large qui soit. Toutefois, nous souhaitons garder la 
ma&icirc;trise de ces documents et nous aimerions &ecirc;tre consult&eacute;s avant toute
diffusion des HowTo's.

Si vous avez des questions, vous pouvez contacter Greg Hankins, le
coordinateur des HowTo Linux HOWTO &agrave; l'adresse &eacute;lectronique suivante :
<tt/gregh@sunsite.unc.edu/ 

<sect>Index

<p>Les entr&eacute;es de cet index sont tri&eacute;es dans l'ordre alphab&eacute;tique.

<itemize>
<item> <tt/-fwritable-strings/ <ref id="index.39" name="39">, <ref id="index.56" name="56"> 
<item> /lib/cpp <ref id="index.16" name="16"> 
<item> a.out <ref id="index.1" name="1"> 
<item> <tt/ar/ <ref id="index.10" name="10"> 
<item> <tt/as/ <ref id="index.8" name="8"> 
<item> &lt;asm/*.h&gt; <ref id="index.19" name="19"> 
<item> <tt/atoi()/ <ref id="index.40" name="40"> 
<item> <tt/atol()/ <ref id="index.41" name="41"> 
<item> ex&eacute;cutables trop gros <ref id="index.63" name="63">, <ref id="index.65" name="65">, <ref id="index.77" name="77"> 
<item> chewing gum <ref id="index.3" name="3"> 
<item> <tt/cos()/ <ref id="index.68" name="68"> 
<item> deboguer <ref id="index.59" name="59"> 
<item> divers <ref id="index.72" name="72"> 
<item> <tt/dlopen()/ <ref id="index.82" name="82"> 
<item> <tt/dlsym()/ <ref id="index.83" name="83"> 
<item> documentation <ref id="index.4" name="4"> 
<item> EINTR <ref id="index.52" name="52"> 
<item> elf <ref id="index.0" name="0">, <ref id="index.71" name="71"> 
<item> <tt/execl()/ <ref id="index.57" name="57"> 
<item> <tt/fcntl/ <ref id="index.47" name="47"> 
<item> <tt/FD_CLR/ <ref id="index.44" name="44"> 
<item> <tt/FD_ISSET/ <ref id="index.45" name="45"> 
<item> <tt/FD_SET/ <ref id="index.43" name="43"> 
<item> <tt/FD_ZERO/ <ref id="index.46" name="46"> 
<item> <tt/fichier/ <ref id="index.2" name="2"> 
<item> &lt;float.h&gt <ref id="index.20" name="20"> 
<item> gcc <ref id="index.6" name="6"> 
<item> <tt/gcc -fomit-frame-pointer/ <ref id="index.61" name="61"> 
<item> <tt/gcc -g/ <ref id="index.60" name="60"> 
<item> gcc -v <ref id="index.14" name="14"> 
<item> gcc, bogues <ref id="index.15" name="15">, <ref id="index.28" name="28">, <ref id="index.29" name="29">, <ref id="index.84" name="84"> 
<item> gcc, options de compilation <ref id="index.13" name="13">, <ref id="index.25" name="25">, <ref id="index.26" name="26"> 
<item> gdb <ref id="index.64" name="64"> 
<item> fichiers d'en-t&ecirc;te <ref id="index.17" name="17"> 
<item> appels syst&egrave;mes interrompus <ref id="index.51" name="51"> 
<item> <tt/ld/ <ref id="index.9" name="9"> 
<item> <tt/LD_*/ : variables d'environnement <ref id="index.80" name="80"> 
<item> ldd <ref id="index.81" name="81"> 
<item> libc <ref id="index.7" name="7"> 
<item> <tt/libg.a/ <ref id="index.62" name="62"> 
<item> libgcc <ref id="index.79" name="79"> 
<item> &lt;limits.h&gt; <ref id="index.21" name="21"> 
<item> lint <ref id="index.58" name="58"> 
<item> &lt;linux/*.h&gt; <ref id="index.18" name="18"> 
<item> <tt/&lt;math.h&gt;/ <ref id="index.70" name="70"> 
<item> maths <ref id="index.69" name="69"> 
<item> <tt/mktemp()/ <ref id="index.55" name="55"> 
<item> num&eacute;ro de version <ref id="index.12" name="12">, <ref id="index.74" name="74"> 
<item> optimisation <ref id="index.27" name="27"> 
<item> pages de manuel <ref id="index.5" name="5"> 
<item> QMAGIC <ref id="index.76" name="76"> 
<item> segmentation fault <ref id="index.30" name="30">, <ref id="index.54" name="54"> 
<item> segmentation fault, in GCC <ref id="index.33" name="33"> 
<item> select() <ref id="index.50" name="50"> 
<item> <tt/SIGBUS/ <ref id="index.34" name="34"> 
<item> <tt/SIGEMT/ <ref id="index.35" name="35"> 
<item> <tt/SIGIOT/ <ref id="index.36" name="36"> 
<item> SIGSEGV <ref id="index.31" name="31">, <ref id="index.53" name="53"> 
<item> SIGSEGV, in gcc <ref id="index.32" name="32"> 
<item> <tt/SIGSYS/ <ref id="index.38" name="38"> 
<item> <tt/SIGTRAP/ <ref id="index.37" name="37"> 
<item> <tt/sin()/ <ref id="index.67" name="67"> 
<item> soname <ref id="index.73" name="73"> 
<item> <tt/sprintf()/ <ref id="index.42" name="42"> 
<item> binaires link&eacute;s statiquement <ref id="index.66" name="66">, <ref id="index.78" name="78"> 
<item> &lt;stdarg.h&gt; <ref id="index.23" name="23"> 
<item> &lt;stddef.h&gt; <ref id="index.24" name="24"> 
<item> <tt/strings/ <ref id="index.11" name="11"> 
<item> <tt>&lt;sys/time.h&gt;</tt> <ref id="index.48" name="48"> 
<item> <tt>&lt;unistd.h&gt;</tt> <ref id="index.49" name="49"> 
<item> &lt;varargs.h&gt; <ref id="index.22" name="22"> 
<item> ZMAGIC <ref id="index.75" name="75"> 
</itemize>

</article>
