/usr/share/doc/HOWTO/fr-html/GCC-HOWTO.html is in doc-linux-fr-html 2013.01-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta name="generator" content=
"HTML Tidy for Linux (vers 25 March 2009), see www.w3.org">
<meta name="GENERATOR" content="LinuxDoc-Tools 0.9.69">
<title>GCC HOWTO pour Linux</title>
</head>
<body>
<h1>GCC HOWTO pour Linux</h1>
<h2>par Daniel Barlow
<code><dan@detached.demon.co.uk></code></h2>
v1.17, 28 février 1996
<hr>
<em>(Adaptation française par Eric Dumas
<code><dumas@freenix.fr></code>, 8 Avril 1996). Ce document
présente la manière de configurer le compilateur GNU
C et les bibliothèques de développement sous Linux.
Il donne un aperçu de la compilation, de l'édition de
liens, de l'exécution et du débogage de programmes
sous Linux. Bon nombre de passages de ce document sont
empruntés à la FAQ GCC rédigée par
Mitch D'Souza's et au HowTo ELF. Ceci est la première
version publique (en dépit du numéro de version : en
fait, ça vient de RCS). N'hésitez pas à me
joindre pour toute remarque.</em>
<hr>
<h2><a name="s1">1. Préliminaires</a></h2>
<h2><a name="index.1"></a> <a name="index.0"></a> <a name=
"ss1.1">1.1 ELF et a.out</a></h2>
<p>Le développement de Linux est actuellement dans une phase
de transition. En résumé, il existe deux formats de
binaires que Linux reconnaît et exécute, et cela
dépend de la manière dont votre système est
configuré : vous pouvez avoir les deux, l'un ou l'autre. En
lisant ce document, vous pourrez savoir quels binaires votre
système est capable de gérer.</p>
<p><a name="index.2"></a></p>
<p>Comment le savoir ? Utilisez la commande <code>file</code> (par
exemple, <code>file /bin/bash</code>). Pour un programme ELF, cette
commande va vous ré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 <code>Linux/i386</code>.</p>
<p>Les différences entre ELF et a.out sont
détaillées plus tard dans ce document. ELF est le
nouveau format et il est considéré comme étant
meilleur.</p>
<h2><a name="index.3"></a> <a name="ss1.2">1.2 Du côté
du copyright</a></h2>
<p>Le copyright et autres informations légales peuvent
être trouvés à la <em>fin</em> de ce document,
avec les avertissements conventionnels concernant la manière
de poser des questions sur Usenet pour éviter d'avoir
à révéler votre ignorance du langage C en
annonçant des bogues qui n'en sont pas, etc.</p>
<h2><a name="ss1.3">1.3 Typographie</a></h2>
<p>Si vous lisez ce document au format Postscript, dvi, ou HTML,
vous pouvez voir quelques différence entre les styles
d'écriture alors que les gens qui consultent ce document au
format texte pur ne verront aucune différence. En
particulier, les noms de fichiers, le nom des commandes, les
messages donnés par les programmes et les codes sources
seront écrits avec le style suivant : <code>style
d'écriture</code>, alors que les noms de variables entre
autres choses seront en <em>italique</em>.</p>
<p>Vous aurez également un index. Avec les formats dvi ou
postscript, les chiffres dans l'index correspondent au
numéros de paragraphes. Au format HTML, il s'agit d'une
numérotation séquentielle pour que vous puissiez
cliquer dessus. Avec le format texte, ce ne sont que des nombres.
Il vous est donc conseillé de prendre un autre format que le
format texte !</p>
<p>L'interpréteur de commande (<em>shell</em>)
utilisé dans les exemples sera la Bourne shell (plutôt
que le C-Shell). Les utilisateurs du C-Shell utiliseront
plutôt :</p>
<blockquote>
<pre>
<code>% setenv soif JD
</code>
</pre></blockquote>
là où j'ai écrit
<blockquote>
<pre>
<code>$ soif=JD; export soif
</code>
</pre></blockquote>
<p>Si l'invite (<em>prompt</em> dans la langue de Shakespeare) est
<code>#</code> plutôt que <code>$</code>, la commande ne
fonctionnera que si elle est exécutée au nom de Root.
Bien sur, je décline toute responsabilité de ce qui
peut se produire sur votre système lors de
l'exécution de ces exemples. Bonne chance
<code>:-)</code></p>
<h2><a name="s2">2. Où récupérer de la
documentation et les programmes ?</a></h2>
<h2><a name="ss2.1">2.1 Ce document</a></h2>
<p>Ce document fait partie de la série des HOWTO pour Linux,
et il est donc disponible ainsi que ces collègues dans les
répertoires HowTo pour Linux, comme sur <a href=
"http://sunsite.unc.edu/pub/linux/docs/HOWTO/">http://sunsite.unc.edu/pub/linux/docs/HOWTO/</a>.
La version HTML peut également être consultée
sur <a href=
"http://ftp.linux.org.uk/~barlow/howto/gcc-howto.html">http://ftp.linux.org.uk/~barlow/howto/gcc-howto.html</a>.</p>
<p>Note du traducteur : vous pouvez obtenir tous les HowTos en
langue anglaise et française sur
<code>ftp.ibp.fr:/pub/linux</code>. Les versions françaises
se trouvent dans le répertoire
<code>/pub/linux/french/HOWTO</code>.</p>
<h2><a name="index.4"></a> <a name="ss2.2">2.2 Autres
documentation</a></h2>
<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 <code>.info</code>. Si vous possédez
une connexion rapide, un CD-ROM ou une certaine patience, vous
pouvez désarchiver la documentation et l'installer dans le
répertoire <code>/usr/info</code>. Sinon, vous pouvez
toujours les trouver sur <a href=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">tsx-11</a>, mais ce
n'est pas nécessairement toujours la dernière
version.</p>
<p><a name="index.5"></a></p>
<p>Il existe deux sources de documentation pour la libc. La libc
GNU est fournie avec des fichiers info qui décrivent assez
précisément la libc Linux sauf pour la partie des
entrées-sorties. Vous pouvez également trouver sur
<a href="ftp://sunsite.unc.edu/pub/Linux/docs/">sunsite</a> des
documents écrits pour Linux ainsi que la description de
certaines appels systèmes (section 2) et certaines fonctions
de la libc (section 3).</p>
<p>Note du traducteur : un bémol concernant cette partie...
La libc Linux n'est pas GNU et tend à être
relativement différente sur certains points.</p>
<h2><a name="index.6"></a> <a name="ss2.3">2.3 GCC</a></h2>
<p>Il existe deux types de réponses</p>
<p>(a) La distribution officielle de GCC pour Linux peut toujours
être récupérée sous la forme de binaires
(déjà compilée) sur <a href=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/</a>.
Vous pouvez la trouver sur le miroir français <a href=
"ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">ftp://ftp.ibp.fr:/pub/linux/packages/GCC/</a>.
A l'heure où j'écris ces lignes, la dernière
version est gcc 2.7.2 (<code>gcc-2.7.2.bin.tar.gz</code>).</p>
<p>(b) La dernière distribution des sources de GCC de la
<em>Free Software Foundation</em> peut-être
récupérée sur <a href=
"ftp://prep.ai.mit.edu/pub/gnu/">prep.ai.mit.edu</a> ou <a href=
"ftp://ftp.ibp.fr/pub/gnu/">ftp.ibp.fr</a>. Ce n'est pas toujours
la même version que celle présentée ci-dessus.
Les mainteneurs de GCC pour Linux ont rendu la compilation de GCC
plus facile grâce à l'utilisation du script
<code>configure</code> qui effectue la configuration d'une
manière automatique. Regardez dans <a href=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">tsx-11</a> ou
<a href="ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">ftp.ibp.fr</a>
pour récupérer d'éventuels patches.</p>
<p>Quelle que soit la complexité de votre programme, vous
aurez également besoin de la <em>libc</em>.</p>
<h2><a name="index.7"></a> <a name="ss2.4">2.4 Les fichiers
d'en-tête et la bibliothèque C</a></h2>
<p>Ce que vous allez trouver dans ce paragraphe dépend</p>
<ul>
<li>de votre système (ELF ou a.out) ;</li>
<li>du type de binaire que vous désirez
générer.</li>
</ul>
Si vous êtes en train de mettre à jour votre libc 4 en
libc 5, vous devriez consulter le ELF HowTo qui se trouve au
même endroit que ce document.
<p>Les libc sont disponibles sur <a href=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">tsx-11</a> ou
<a href="ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">ftp.ibp.fr</a>.
Voici une description des fichiers situés dans ce
répertoire :</p>
<dl>
<dt><b><code>libc-5.2.18.bin.tar.gz</code></b></dt>
<dd>
<p>--- bibliothèques dynamiques et statiques ELF plus les
fichiers d'en-tête pour la bibliothèque C et la
bibliothèque mathématique.</p>
</dd>
<dt><b><code>libc-5.2.18.tar.gz</code></b></dt>
<dd>
<p>--- Code source pour la bibliothèque ci-dessus. Vous
aurez également besoin du paquetage <code>.bin.</code> pour
avoir les fichiers d'en-tête. Si vous hésitez entre
compiler la bibliothèque C vous-même et utiliser les
binaires, la bonne réponse est dans la majorité des
cas est d'utiliser les binaires. Toutefois, si vous désirer
utiliser NYS (NdT : NYS != NIS) ou bien les mots de passe
<em>shadow</em>, vous devrez recompiler la libc par
vous-même.</p>
</dd>
<dt><b><code>libc-4.7.5.bin.tar.gz</code></b></dt>
<dd>
<p>--- bibliothèques dynamiques et statiques a.out pour la
version 4.7.5 de la libc. Cette bibliothèque a
été conçue pour pouvoir coexister avec le
paquetage de la libc 5 décrit ci-dessus, mais c'est
uniquement nécessaire si vous désirez utiliser ou
développer des programmes au format a.out.</p>
</dd>
</dl>
<h2><a name="index.11"></a> <a name="index.10"></a> <a name=
"index.9"></a> <a name="index.8"></a> <a name="ss2.5">2.5 Outils
associés (as, ld, ar, strings, etc.)</a></h2>
<p>Ces outils se trouvent comme les bibliothèques dans le
répertoire <a href=
"ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/">tsx-11</a>, et
<a href="ftp://ftp.ibp.fr:/pub/linux/packages/GCC/">ftp.ibp.fr</a>.
La version actuelle est
<code>binutils-2.6.0.2.bin.tar.gz</code>.</p>
<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ème lorsqu'elle est utilisée avec
la libc ELF. Le développement de la libc est relativement
rapide et à moins que n'ayez de bonnes raisons pour utiliser
le format a.out, vous êtes encouragés à suivre
le mouvement.</p>
<h2><a name="s3">3. Installation et configuration de GCC</a></h2>
<h2><a name="index.14"></a> <a name="index.13"></a> <a name=
"index.12"></a> <a name="ss3.1">3.1 Les versions de GCC</a></h2>
<p>Vous pouvez savoir quelle est la version de GCC que vous
possédez en tapant <code>gcc -v</code> lors de l'invite.
C'est également une bonne technique pour savoir si votre
configuration est ELF ou a.out. Sur mon système, cela donne
ceci :</p>
<blockquote>
<pre>
<code>$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-zorglub-linux/2.7.2/specs
gcc version 2.7.2
</code>
</pre></blockquote>
<p>Les mots-clefs à remarquer</p>
<ul>
<li><code>i486</code>. Cela vous indique que la version de gcc que
vous utilisez a été compilée pour être
utilisée sur un processeur 486 --- mais vous pouvez avoir un
autre processeur comme un 386 ou un Pentium (586). Tous ces
processeurs peuvent exécuter le code compilé avec
n'importe quel processeur. La seule différence réside
dans le fait que le code 486 rajoute un peu de code à
certains endroits pour aller plus vite sur un 486. Cela n'a pas
d'effet néfaste côté performance sur un 386
mais cela rend les exécutables un peu plus importants.</li>
<li><code>zorglub</code>. Ce n'est pas réellement important,
et il s'agit généralement d'un commentaire (comme
<code>slackware</code> or <code>debian</code>) ou même, cela
peut-être vide (lorsque vous avez comme nom de
répertoire <code>i486-linux</code>). Si vous construisez
votre propre gcc, vous pouvez fixer ce paramètre selon vos
désirs, comme je l'ai fait. <code>:-)</code></li>
<li><code>linux</code>. Cela peut être à la place
<code>linuxelf</code> ou <code>linuxaout</code> et en fait, la
signification varie en fonction de la version que vous
possédez.
<ul>
<li><code>linux</code> signifie ELF si la version est 2.7.0 ou
supérieure, sinon, c'est du a.out.</li>
<li><code>linuxaout</code> signifie a.out. Cela a été
introduit comme cible lorsque le format des binaires a
changé de a.out vers ELF dans <b>Linux</b>. Normalement,
vous ne verrez plus de <code>linuxaout</code> avec une version de
gcc supérieure à 2.7.0. <a name="index.15"></a></li>
<li><code>linuxelf</code> est dépassé. Il s'agit
généralement de gcc version 2.6.3 configuré
pour générer des exécutables ELF. Notez que
gcc 2.6.3 est connu pour générer de nombreuses
erreurs lorsqu'il produit du code ELF --- une mise à jour
est très fortement recommandée.</li>
</ul>
</li>
<li><code>2.7.2</code> est le numéro de la version de
GCC.</li>
</ul>
<p>Donc, en résumé, nous possédons gcc 2.7.2
qui génère du code ELF. <em>Quelle surprise</em>
(NdT: En français dans le texte) !</p>
<h2><a name="ss3.2">3.2 A quel endroit s'installe GCC ?</a></h2>
<p>Si vous avez installé gcc sans regarder, ou bien si vous
l'avez eu à partir d'une distribution, vous pouvez avoir
envie de savoir où il se trouve dans votre arborescence. Les
mots clefs permettant cela sont</p>
<ul>
<li>
<code>/usr/lib/gcc-lib/</code><em>machine-cible</em><code>/</code><em>version</em><code>/</code>
(et ses sous-répertoires) est généralement
l'endroit où se trouve le plus souvent le compilateur. Ceci
inclut les exécutables qui réalisent la compilation
ainsi que certaines bibliothèques et quelques fichiers
d'en-tête.</li>
<li><code>/usr/bin/gcc</code> est le lanceur du compilateur ---
c'est en fait le programme que vous lancez. Il peut être
utilisé avec plusieurs versions de gcc lorsque vous
possédez plusieurs répertoires installés (voir
plus bas). Pour trouver la version par défaut
utilisée, lancez <code>gcc -v</code>. Pour forcer
l'utilisation d'une autre version, lancez <code>gcc -V</code>
<em>version</em>. Par exemple,
<blockquote>
<pre>
<code># 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
</code>
</pre></blockquote>
</li>
<li>
<code>/usr/</code><em>machine-cible</em><code>/(bin|lib|include)/</code>.
Si vous avez installé plusieurs cibles possibles (par
exemple a.out et elf, ou bien un compilateur croisé, les
bibliothèques, les binutils (<code>as</code>,
<code>ld</code>, etc.) et les fichiers d'en-tête pour les
cibles différente de celle par défaut peuvent
être trouvés à cet endroit. Même si vous
n'avez qu'une seule version de gcc installée, vous devriez
toutefois trouver à cet endroit un certain nombre de
fichiers. Si ce n'est pas la cas, regardez dans
<code>/usr/(bin|lib|include)</code>.</li>
<li><code>/lib/</code>, <code>/usr/lib</code> et autres sont les
répertoires pour les bibliothèques pour le
système initial. Vous aurez également besoin du
programme <code>/lib/cpp</code> pour un grand nombre d'applications
(X l'utilise beaucoup) --- soit vous le copiez à partir de
<code>/usr/lib/gcc-lib/</code><em>machine-cible</em><code>/</code><em>version</em><code>/</code>,
soit vous faites pointer un lien symbolique dessus. <a name=
"index.16"></a></li>
</ul>
<h2><a name="index.17"></a> <a name="ss3.3">3.3 Où se
trouvent les fichiers d'en-tête ?</a></h2>
<p>Si l'on excepte les fichier fichiers d'en-tête que vous
installez dans le répertoire
<code>/usr/local/include</code>, il y a en fait trois types de
fichiers d'en-tête :</p>
<ul>
<li>La grande majorité des fichiers situés dans le
répertoire <code>/usr/include/</code> et dans ses
sous-répertoires proviennent du paquetage de la libc dont
s'occupe H.J. Lu. Je dis bien la "grande majorité" car vous
pouvez avoir également certains fichiers provenant d'autres
sources (par exemple des bibliothèques <code>curses</code>
et <code>dbm</code>), ceci est d'autant plus vrai si vous
possédez une distribution de la libc récente
(où les bibliothèques curses et dbm ne sont pas
intégrées). <a name="index.18"></a> <a name=
"index.19"></a></li>
<li>Les répertoires <code>/usr/include/linux</code> et
<code>/usr/include/asm</code> (pour les fichiers
<code><linux/*.h></code> et <code><asm/*.h></code>)
doivent être des liens symboliques vers les
répertoires <code>linux/include/linux</code> et
<code>linux/include/asm</code> situés dans les sources du
noyau. Vous devrez installer ces sources si vous désirez
pouvoir développer : ces sources ne sont pas utilisés
uniquement pour compiler le noyau. Il est probable que vous ayez
besoin de lancer la commande suivante <code>make config</code> dans
le répertoire des sources du noyau après les avoir
installés. Beaucoup de fichiers ont besoin du fichier
d'en-tête <code><linux/autoconf.h></code> qui n'existe
pas sans cette commande. Il est à noter que dans certaines
versions du noyau, le répertoire <code>asm</code> est en
fait un lien symbolique qui n'est créé qu'avec
l'exécution de <code>make config</code>. Donc, si vous
installez les sources du noyau dans le répertoire
<code>/usr/src/linux</code>, il suffit de faire :
<blockquote>
<pre>
<code>$ 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 .
</code>
</pre></blockquote>
<a name="index.20"></a> <a name="index.21"></a> <a name=
"index.22"></a> <a name="index.23"></a> <a name=
"index.24"></a></li>
<li>Les fichiers tels que <code><float.h></code>,
<code><limits.h></code>, <code><varargs.h></code>,
<code><stdarg.h></code> et <code><stddef.h></code>
changent en fonction de la version du compilateur, et peuvent
être trouvés dans le répertoire
<code>/usr/lib/gcc-lib/i486-box-linux/2.7.2/include/</code> pour la
version <code>2.7.2</code>.</li>
</ul>
<h2><a name="ss3.4">3.4 Construire un compilateur
croisé</a></h2>
<h3>Linux comme plate-forme de destination</h3>
<p>Nous supposons que vous avez récupéré les
sources de gcc, et normalement, il vous suffit de suivre les
instructions données dans le fichier <code>INSTALL</code>
situé dans les sources de gcc. Ensuite, il suffit de lancer
<code>configure --target=i486-linux --host=XXX</code> sur une
plateforme <code>XXX</code>, puit un <code>make</code> devrait
compiler gcc correctement. Il est à noter que vous aurez
besoin des fichiers d'en-tête de Linux, ainsi que les sources
de l'assembleur et du l'éditeur de liens croisés que
vous pouvez trouver sur <a href=
"ftp://tsx-11.mit.edu/pub/linux/packages/GCC/">ftp://tsx-11.mit.edu/pub/linux/packages/GCC/</a>
ou <a href=
"ftp://ftp.ibp.fr/pub/linux/GCC/">ftp://ftp.ibp.fr/pub/linux/GCC/</a>.</p>
<h3>Linux comme plate-forme origine et MSDOS comme destination</h3>
<p>Arggg. Apparemment, cela est possible en utilisant le paquetage
« emx » ou l'extension « go ». Regardez
<a href=
"ftp://sunsite.unc.edu/pub/Linux/devel/msdos">ftp://sunsite.unc.edu/pub/Linux/devel/msdos</a>
pour plus d'informations.</p>
<p>Je n'ai pas testé cela et je ne pense pas le faire !</p>
<h2><a name="s4">4. Portage et compilation</a></h2>
<h2><a name="index.25"></a> <a name="ss4.1">4.1 Symboles
définis automatiquement</a></h2>
<p>Vous pouvez trouver quels symboles votre version de gcc
définit automatiquement en le lançant avec l'option
<code>-v</code>. Par exemple cela donne ça chez moi :</p>
<blockquote>
<pre>
<code>$ 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__ -
</code>
</pre></blockquote>
Si vous écrivez du code qui utilise des
spécificités Linux, il est souhaitable
d'implémenter le code non portable de la manière
suivante
<blockquote>
<pre>
<code>#ifdef __linux__
/* ... code linux ... */
#endif /* linux */
</code>
</pre></blockquote>
<p>Utilisez <code>__linux__</code> pour cela, et <em>pas</em>
<code>linux</code>. Bien que cette macro soit définie, ce
n'est pas une spécification POSIX.</p>
<h2><a name="ss4.2">4.2 Options de compilation</a></h2>
<p>La documentation des options de compilation se trouve dans les
pages <em>info</em> de gcc (sous Emacs, utilisez <code>C-h i</code>
puis sélectionnez l'option `gcc'). Votre distribution peut
ne pas avoir installé la documentation ou bien vous pouvez
en avoir une ancienne. Dans ce cas, la meilleure chose à
faire est de récupérer les sources de gcc depuis
<a href=
"ftp://prep.ai.mit.edu/pub/gnu">ftp://prep.ai.mit.edu/pub/gnu</a>
ou l'un des ses nombreux miroirs dont <a href=
"ftp://ftp.ibp.fr/pub/gnu">ftp://ftp.ibp.fr/pub/gnu</a>.</p>
<p>La page de manuel gcc (<code>gcc.1</code>) est en principe,
complètement dépassée. Cela vous met en garde
si vous désirez la consulter.</p>
<h3><a name="index.27"></a> <a name="index.26"></a> Options de
compilation</h3>
<p>gcc peut réaliser un certain nombre d'optimisations sur
le code généré en ajoutant l'option
<code>-O</code><em>n</em> à la ligne de commandes, où
<em>n</em> est un chiffre. La valeur de <em>n</em>, et son effet
exact, dépend de la version de gcc, mais s'échelonne
normalement entre 0 (aucune optimisation) et 2 (un certain nombre)
ou 3 (toutes les optimisations possibles).</p>
<p>En interne, gcc interprète les options telles que
<code>-f</code> et <code>-m</code>. Vous pouvez voir exactement ce
qu'effectue le niveau spécifié dans l'option
<code>-O</code> en lançant gcc avec l'option <code>-v</code>
et l'option (non documentée) <code>-Q</code>. Par exemple,
l'option <code>-O2</code>, effectue les opérations suivantes
sur ma machine :</p>
<blockquote>
<pre>
<code>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
</code>
</pre></blockquote>
<p>Utiliser un niveau d'optimisation supérieur à
celui que le compilateur supporte (par exemple <code>-O6</code>)
aura le même effet qu'utiliser le plus haut niveau
géré. Distribuer du code où la compilation est
configurée de cette manière est une très
mauvaise idée -- si d'autres optimisations sont
incorporées dans de versions futures, vous (ou d'autres
utilisateurs) pouvez vous apercevoir que cela ne compile plus, ou
bien que le code généré ne fait pas les
actions désirées.</p>
<p><a name="index.28"></a> Les utilisateurs de gcc 2.7.0 à
2.7.2 devraient noter qu'il y a un bogue dans l'option
<code>-O2</code>. Plus précisément, la <em>strength
reduction</em> ne fonctionne pas. Un patch a été
implémenté pour résoudre ce problème,
mais vous devez alors recompiler gcc. Sinon, vous devrez toujours
compiler avec l'option <code>-fno-strength-reduce</code>.</p>
<h3>Spécification du processeur</h3>
<p>Il existe d'autres options <code>-m</code> qui ne sont pas
positionnées lors de l'utilisation de <code>-O</code> mais
qui sont néanmoins utiles dans certains cas. C'est le cas
pour les options <code>-m386</code> et <code>-m486</code>, qui
indiquent à gcc de générer un code plus ou
moins optimisé pour l'un ou l'autre type de processeur. Le
code continuera à fonctionner sur les deux processeurs. Bien
que le code pour 486 soit plus important, il ne ralentit pas
l'exécution du programme sur 386.</p>
<p>Il n'existe pas actuellement de <code>-mpentium</code> ou
<code>-m586</code>. Linus a suggéré l'utilisation des
options <code>-m486 -malign-loops=2 -malign-jumps=2
-malign-functions=2</code>, pour exploiter les optimisations du 486
tout en perdant de la place due aux problèmes d'alignements
(dont le Pentium n'a que faire). Michael Meissner (de Cygnus) nous
dit :</p>
<blockquote>« Mon avis est que l'option
<code>-mno-strength-reduce</code> 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ème). Cela s'explique
en raison du peu de registres dont disposent ces processeurs (et la
méthode de GCC qui consiste à 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
à rajouter des registres pour remplacer les multiplications
par des additions. Je suspecte également
<code>-fcaller-saves</code> de ne pas arranger la situation.
»</blockquote>
<blockquote>Une autre idée est que
<code>-fomit-frame-pointer</code> n'est pas obligatoirement une
bonne idée. D'un côté, cela peut signifier
qu'un autre registre est disponible pour une allocation. D'un autre
côté, vue la maniè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êtres relatives, ce qui signifie en clair que moins de
cache est disponible pour l'exécution du processus. Il faut
préciser que l'option <code>-fomit-frame-pointer</code>,
signifie que le compilateur doit constamment ajuster le pointeur de
pile après les appels, alors qu'avec une fenêtre, il
peut laisser plusieurs appels dans la pile.</blockquote>
<p>Le mot final sur le sujet provient de Linus :</p>
<blockquote>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éelle optimisation que pour vous.</blockquote>
<h3><a name="index.33"></a> <a name="index.32"></a> <a name=
"index.31"></a> <a name="index.30"></a> <a name="index.29"></a>
<code>Internal compiler error: cc1 got fatal signal 11</code></h3>
<p>Signal 11 correspond au signal SIGSEGV, ou bien <em>segmentation
violation</em>. Normalement, cela signifie que le programme s'est
mélangé les pointeurs et a essayé
d'écrire là où il n'en a pas le droit. Donc,
cela pourrait être un bug de gcc.</p>
<p>Toutefois, gcc est un logiciel assez testé et assez
remarquable de ce côté. Il utilise un grand nombre de
structures de données complexes, et un nombre impressionnant
de pointeurs. En résumé, c'est le plus pointilleux
des testeurs de mémoire existants. Si vous <em>n'arrivez pas
à reproduire le bogue</em> --- si cela ne s'arrête pas
au même endroit lorsque vous retentez la compilation ---
c'est plutôt un problème avec votre machine
(processeur, mémoire, carte mère ou bien cache).
<b>N'annoncez pas</b> la dé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ême si le noyau s'arrête lors du
`<code>make zImage</code>' ! `<code>make zImage</code>' doit
compiler plus de 200 fichiers, et il en faut bien moins pour
arriver à faire échouer une compilation.</p>
<p>Si vous arrivez à reproduire le bogue et (mieux encore)
à écrire un petit programme qui permet de mettre en
évidence cette erreur, alors vous pouvez envoyer le code
soit à la FSF, soit dans la liste linux-gcc. Consultez la
documentation de gcc pour plus de détails concernant les
informations nécessaires.</p>
<h2><a name="ss4.3">4.3 Portabilité</a></h2>
<p>Cette phrase a été dite un jour : si quelque chose
n'a pas été porté vers Linux alors ce n'est
pas important de l'avoir :-).</p>
<p>Plus sérieusement, en général seules
quelques modifications mineures sont nécessaires car Linux
répond à 100% aux spécifications POSIX. Il est
généralement sympathique d'envoyer à l'auteur
du programme les modifications effectuées pour que le
programme fonctionne sur Linux, pour que lors d'une future version,
un `make' suffise pour générer
l'exécutable.</p>
<h3>Spécificités BSD (notamment
<code>bsd_ioctl</code>, <code>daemon</code> et
<code><sgtty.h></code>)</h3>
<p>Vous pouvez compiler votre programme avec l'option
<code>-I/usr/include/bsd</code> et faire l'édition de liens
avec <code>-lbsd</code> (en ajoutant
<code>-I/usr/include/bsd</code> à la ligne
<code>CFLAGS</code> et <code>-lbsd</code> à la ligne
<code>LDFLAGS</code> dans votre fichier <code>Makefile</code>). Il
est également nécessaire de ne <b>pas</b> ajouter
<code>-D__USE_BSD_SIGNAL</code> si vous voulez que les signaux BSD
fonctionnent car vous les avez inclus automatiquement avec la ligne
<code>-I/usr/include/bsd</code> et en incluant le fichier
d'en-tête <code><signal.h></code>.</p>
<h3><a name="index.38"></a> <a name="index.37"></a> <a name=
"index.36"></a> <a name="index.35"></a> <a name="index.34"></a>
Signaux <em>manquants</em> (<code>SIGBUS</code>,
<code>SIGEMT</code>, <code>SIGIOT</code>, <code>SIGTRAP</code>,
<code>SIGSYS</code>, etc.)</h3>
<p>Linux respecte les spé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) :</p>
<blockquote>« Les signaux SIGBUS, SIGEMT, SIGIOT, SIGTRAP, et
SIGSYS ont été omis de la norme POSIX.1 car leur
comportement est dépendant de l'implémentation et
donc ne peut être répertorié d'une
manière satisfaisante. Certaines implémentations
peuvent fournir ces signaux mais doivent documenter leur effet
»</blockquote>
<p>La manière la plus élégante de
régler ce problème est de redéfinir ces
signaux à <code>SIGUNUSED</code>. La manière
<em>normale</em> de procéder est d'entourer le code avec les
<code>#ifdef</code> appropriés :</p>
<blockquote>
<pre>
<code>#ifdef SIGSYS
/* ... code utilisant les signaux non posix .... */
#endif
</code>
</pre></blockquote>
<h3><a name="index.39"></a> Code K & R</h3>
<p>GCC est un compilateur ANSI, or il existe beaucoup de code qui
ne soit pas ANSI.</p>
<p>Il n'y a pas grand chose à faire, sauf rajouter l'option
<code>-traditional</code> lors de la compilation. Il effectue
certaines vérifications supplémentaires. Consultez
les pages info gcc.</p>
<p>Notez que l'option <code>-traditional</code> a pour unique effet
de changer la forme du langage accepté par gcc. Par exemple,
elle active l'option <code>-fwritable-strings</code>, qui
déplace toutes les chaînes de caractères vers
l'espace de données (depuis l'espace de texte, où
elle ne peuvent pas être modifiées). Ceci augmente la
taille de la mémoire occupée par le programme.</p>
<h3><a name="index.41"></a> <a name="index.40"></a> Les symboles du
préprocesseur produisent un conflit avec les prototypes du
code</h3>
<p>Un des problèmes fréquents se produit lorsque
certaines fonctions standards sont définies comme macros
dans les fichiers d'en-tête de Linux et le
préprocesseur refusera de traiter des prototypes identiques.
Par exemple, cela peut arriver avec <code>atoi()</code> et
<code>atol()</code>.</p>
<h3><a name="index.42"></a> <code>sprintf()</code></h3>
<p>Parfois, soyez prudent lorsque vous effectuez un portage
à partir des sources de programmes fonctionnant sous SunOs,
surtout avec la fonction <code>sprintf(string, fmt, ...)</code> car
elle renvoie un pointeur sur la chaîne de caractères
alors que Linux (suivant la norme ANSI) retourne le nombre de
caractères recopiés dans la chaîne de
caractères.</p>
<h3><a name="index.49"></a> <a name="index.48"></a> <a name=
"index.47"></a> <a name="index.46"></a> <a name="index.45"></a>
<a name="index.44"></a> <a name="index.43"></a> <code>fcntl</code>
et ses copains. Où se trouve la définition de
<code>FD_*</code> et compagnie ?</h3>
<p>Dans <code><sys/time.h></code>. Si vous utilisez
<code>fcntl</code> vous voudrez probablement inclure
<code><unistd.h></code> également, pour avoir le
prototype de la fonction.</p>
<p>D'une manière générale, la page de manuel
pour une fonction donne la liste des fichiers d'en-tête
à inclure.</p>
<h3><a name="index.50"></a> Le timeout de <code>select()</code>.
Les programmes commencent dans un état d'attente active</h3>
<p>A une certaine époque, le paramètre timeout de la
fonction <code>select()</code> était utilisé en
lecture seule. C'est pourquoi la page de manuel comporte une mise
en garde :</p>
<blockquote>select() devrait retourner normalement le temps
écoulé depuis le timeout initial, s'il s'est
déclenché, en modifiant la valeur pointée par
le paramètre <code>time</code>. Cela sera peut-être
implémenté dans les versions ultérieures du
système. Donc, il n'est pas vraiment prudent de supposer que
les données pointées ne seront pas modifiées
lors de l'appel à select().</blockquote>
<p>Mais tout arrive avec le temps ! Lors d'un retour de
<code>select()</code>, l'argument <code>timeout</code> recevra le
temps écoulé depuis la dernière
réception de données. Si aucune donnée n'est
arrivée, la valeur sera nulle, et les futurs appels à
cette fonction utilisant le même <code>timeout</code> auront
pour résultat un retour immédiat.</p>
<p>Pour résoudre le problème, il suffit de mettre la
valeur <code>timeout</code> dans la structure à chaque appel
de <code>select()</code>. Le code initial était</p>
<blockquote>
<pre>
<code> struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
while (some_condition)
select(n,readfds,writefds,exceptfds,&timeout);
</code>
</pre></blockquote>
et doit devenir :
<blockquote>
<pre>
<code> struct timeval timeout;
while (some_condition)
{
timeout.tv_sec = 1;
timeout.tv_usec = 0;
select(n,readfds,writefds,exceptfds,&timeout);
}
</code>
</pre></blockquote>
<p>Certaines versions de Mosaic étaient connues à une
certaine époque pour avoir ce problème.</p>
<p>La vitesse de rotation du globe terrestre était
inversement proportionnelle à la vitesse de transfert des
données !</p>
<h3><a name="index.52"></a> <a name="index.51"></a> Appels
systèmes interrompus</h3>
<h3>Symptomes :</h3>
<p>Lorsqu'un processus est arrêté avec un Ctrl-Z et
relancé - ou bien lorsqu'un autre signal est
déclenché dans une situation différente : par
exemple avec un Ctrl-C, la terminaison d'un processus, etc, on dit
qu'il y a « interruption d'un appel système » ,
ou bien « write : erreur inconnue » ou des trucs de ce
genre.</p>
<h3>Problèmes :</h3>
<p>Les systèmes POSIX vérifient les signaux plus
souvent que d'autres Unix plus anciens. Linux peux lancer les
gestionnaires de signaux :</p>
<ul>
<li>d'une manière asynchrone (sur un top d'horloge)</li>
<li>lors d'un retour de n'importe quel appel système</li>
<li>pendant l'exécution des appels systèmes suivants
: <code>select()</code>, <code>pause()</code>,
<code>connect()</code>, <code>accept()</code>, <code>read()</code>
sur des terminaux, des sockets, des pipes ou des fichiers
situés dans <code>/proc</code>, <code>write()</code> sur des
terminaux, des sockets, des pipes ou des imprimantes,
<code>open()</code> sur des FIFOs, des lignes PTYs ou
séries, <code>ioctl()</code> sur des terminaux,
<code>fcntl()</code> avec la commande <code>F_SETLKW</code>,
<code>wait4()</code>, <code>syslog()</code>, et toute
opération d'ordre TCP ou NFS.</li>
</ul>
<p>Sur d'autres systèmes d'exploitation, il est possible que
vous ayez à inclure dans cette catégorie les appels
systèmes suivants : <code>creat()</code>,
<code>close()</code>, <code>getmsg()</code>, <code>putmsg()</code>,
<code>msgrcv()</code>, <code>msgsnd()</code>, <code>recv()</code>,
<code>send()</code>, <code>wait()</code>, <code>waitpid()</code>,
<code>wait3()</code>, <code>tcdrain()</code>,
<code>sigpause()</code>, <code>semop()</code>.</p>
<p>Si un signal (que le programme désire traiter) est
lancé pendant l'exécution d'un appel système,
le gestionnaire est lancé. Lorsque le gestionnaire du signal
se termine, l'appel système détecte qu'il a
été interrompu et se termine avec la valeur -1 et
<code>errno = EINTR</code>. Le programme n'est pas forcément
au courant de ce qui s'est passé et donc s'arrête.</p>
<p>Vous pouvez choisir deux solutions pour résoudre ce
problème.</p>
<p>(1)Dans tout gestionnaire de signaux que vous mettez en place,
ajoutez l'option <code>SA_RESTART</code> au niveau de
<em>sigaction</em>. Par exemple, modifiez</p>
<blockquote>
<pre>
<code> signal (signal_id, mon_gestionnaire_de_signaux);
</code>
</pre></blockquote>
en
<blockquote>
<pre>
<code> 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);
}
</code>
</pre></blockquote>
<p>Notez que lors de certains appels systèmes vous devrez
souvent regarder si <code>errno</code> n'a pas été
positionnée à <code>EINTR</code> par vous même
comme avec <code>read()</code>, <code>write()</code>,
<code>ioctl()</code>, <code>select()</code>, <code>pause()</code>
et <code>connect()</code>.</p>
<p>(2) A la recherche de <code>EINTR</code> :</p>
<p>Voici deux exemples avec <code>read()</code> et
<code>ioctl()</code>,</p>
<p>Voici le code original utilisant <code>read()</code></p>
<blockquote>
<pre>
<code>int result;
while (len > 0)
{
result = read(fd,buffer,len);
if (result < 0)
break;
buffer += result;
len -= result;
}
</code>
</pre></blockquote>
et le nouveau code
<blockquote>
<pre>
<code>int result;
while (len > 0)
{
result = read(fd,buffer,len);
if (result < 0)
{
if (errno != EINTR)
break;
}
else
{
buffer += result;
len -= result;
}
}
</code>
</pre></blockquote>
Voici un code utilisant <code>ioctl()</code>
<blockquote>
<pre>
<code>int result;
result = ioctl(fd,cmd,addr);
</code>
</pre></blockquote>
et cela devient
<blockquote>
<pre>
<code>int result;
do
{
result = ioctl(fd,cmd,addr);
}
while ((result == -1) && (errno == EINTR));
</code>
</pre></blockquote>
<p>Il faut remarquer que dans certaines versions d'Unix de type BSD
on a l'habitude de relancer l'appel système. Pour
récupérer les interruptions d'appels systèmes,
vous devez utiliser les options <code>SV_INTERRUPT</code> ou
<code>SA_INTERRUPT</code>.</p>
<h3><a name="index.56"></a> <a name="index.55"></a> <a name=
"index.54"></a> <a name="index.53"></a> Les chaînes et leurs
accès en écritures (ou les programmes qui provoquent
des « segmentation fault » d'une manière
aléatoire)</h3>
<p>GCC a une vue optimiste en ce qui concerne ses utilisateurs, en
croyant qu'ils respectent le fait qu'une chaîne dite
constante l'est réellement. Donc, il les range dans la zone
<em>texte(code)</em> du programme, où elles peuvent
être chargées puis déchargées à
partir de l'image binaire de l'exécutable située sur
disque (ce qui évite d'occuper de l'espace disque). Donc,
toute tentative d'écriture dans cette chaîne provoque
un « segmentation fault ».</p>
<p>Cela peut poser certains problèmes avec d'anciens codes,
par exemple ceux qui utilisent la fonction <code>mktemp()</code>
avec une chaîne constante comme argument.
<code>mktemp()</code> essaye d'écrire dans la chaîne
passée en argument.</p>
<p>Pour résoudre ce problème,</p>
<ol>
<li>compilez avec l'option <code>-fwritable-strings</code> pour
indiquer à gcc de mettre les chaînes constantes dans
l'espace de données</li>
<li>réécrire les différentes parties du code
pour allouer une chaîne non constante puis effectuer un
strcpy des données dedans avant d'effectuer l'appel.</li>
</ol>
<h3><a name="index.57"></a> Pourquoi l'appel à
<code>execl()</code> échoue ?</h3>
<p>Tout simplement parce que vous l'utilisez mal. Le premier
argument d'<code>execl</code> est le programme que vous
désirez exécuter. Le second et ainsi de suite sont en
fait le éléments du tableau <code>argv</code> que
vous appelez. Souvenez-vous que <code>argv[0]</code> est
traditionnellement fixé même si un programme est
lancé sans argument. Vous devriez donc écrire :</p>
<blockquote>
<pre>
<code>execl("/bin/ls","ls",NULL);
</code>
</pre></blockquote>
et pas
<blockquote>
<pre>
<code>execl("/bin/ls", NULL);
</code>
</pre></blockquote>
<p>Lancer le programme sans argument est considéré
comme étant une demande d'affichage des bibliothèques
dynamiques associées au programme, si vous utilisez le
format a.out. ELF fonctionne d'une manière
différente.</p>
<p>(Si vous désirez ces informations, il existe des outils
plus simples; consultez la section sur le chargement dynamique, ou
la page de manuel de <code>ldd</code>).</p>
<h2><a name="s5">5. Déboguer et optimiser</a></h2>
<h2><a name="index.58"></a> <a name="ss5.1">5.1 Etude
préventive du code (lint)</a></h2>
<p>Il n'existe pas de lint qui soit réellement utilisable,
tout simplement parce que la grande majorité des
développeurs sont satisfaits des messages d'avertissement de
gcc. Il est probable que l'option la plus utile est l'option
<code>-Wall</code> --- qui a pour effet d'afficher tous les
avertissements possibles.</p>
<p>Il existe une version du domaine public du programme lint que
vous pouvez trouver à l'adresse suivante : <a href=
"ftp://larch.lcs.mit.edu/pub/Larch/lclint">ftp://larch.lcs.mit.edu/pub/Larch/lclint</a>.
Je ne sais pas ce qu'elle vaut.</p>
<h2><a name="index.59"></a> <a name="ss5.2">5.2
Déboguer</a></h2>
<h3><a name="index.62"></a> <a name="index.61"></a> <a name=
"index.60"></a> Comment rendre débogable un programme ?</h3>
<p>Vous devez compiler et effectuer l'édition de liens avec
l'option <code>-g</code>, et sans l'option
<code>-fomit-frame-pointer</code>. En fait, vous ne devez compiler
que les modules que vous avez besoin de déboguer.</p>
<p>Si vous possédez un système a.out, les
bibliothèques dynamiques sont compilées avec l'option
<code>-fomit-frame-pointer</code>, que gcc ne peut pas
gérer. Lorsque vous compilez avec l'option <code>-g</code>,
alors par défaut vous effectuez une édition de liens
statique, ce qui permet de résoudre le problème.</p>
<p>Si l'éditeur de liens échoue avec un message
disant qu'il n'arrive pas à trouver la bibliothèque
libg.a, c'est que vous ne possédez pas la
bibliothèque <code>/usr/lib/libg.a</code>, qui est la
bibliothèque C standard permettant le débogage. Cette
bibliothèque est fournie dans le paquetage des binaires de
la libc., ou (dans les nouvelles versions) vous aurez besoin de
récupérer le source et de le compiler
vous-même. Vous n'avez pas réellement besoin de cela
en fait, vous pouvez faire un lien logique vers
<code>/usr/lib/libc.a</code></p>
<h3><a name="index.63"></a> Comment réduire la taille des
exécutables ?</h3>
<p>Bon nombre de produits GNU sont fournis pour compiler avec
l'option <code>-g</code>, ce qui génère des
exécutables d'une taille très importante (et souvent
l'édition de liens s'effectue d'une manière
statique). Ce n'est pas une idée lumineuse...</p>
<p>Si le programme possède le script <code>configure</code>
généré par autoconf, vous pouvez modifier les
options de débogage en effectuant un <code>./configure
CFLAGS=</code> ou <code>./configure CFLAGS=-O2</code>. Sinon, vous
pouvez aller modifier le Makefile. Bien sûr, si vous utilisez
le format ELF, l'édition de liens sera effectuée de
manière dynamique même avec l'option <code>-g</code>.
Dans ce cas, vous pouvez effectuer un strip sur
l'exécutable.</p>
<h3><a name="index.64"></a> Programmes disponibles</h3>
<p>Beaucoup de gens utilisent <b>gdb</b>, que vous pouvez
récupérer sur le site <a href=
"ftp://prep.ai.mit.edu/pub/gnu">prep.ai.mit.edu</a>, sous une forme
binaire sur <a href=
"ftp://tsx-11.mit.edu/pub/linux/packages/GCC">tsx-11</a> ou sur
sunsite. <b>xxgdb</b> est une surcouche X de gdb (c.a.d. que vous
avez besoin de gdb pour utiliser xxgdb). Les sources peuvent
être récupérés sur <a href=
"ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz">ftp://ftp.x.org/contrib/xxgdb-1.08.tar.gz</a></p>
<p>Il existe également le débogueur <b>UPS</b> qui a
été porté par Rick Sladkey. Il fonctionne sous
X également, mais à la différence d'xxgdb, ce
n'est qu'une surcouche X pour un débogueur en mode en texte.
Il possède certaines caractéristiques très
intéressantes et si vous utilisez beaucoup ce genre
d'outils, vous l'essayerez sûrement. Les patches ainsi que
des versions précompilées pour Linux peuvent
être trouvées sur <a href=
"ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/">ftp://sunsite.unc.edu/pub/Linux/devel/debuggers/</a>,
et les sources peuvent être récupérés
sur <a href=
"ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z">ftp://ftp.x.org/contrib/ups-2.45.2.tar.Z</a>.</p>
<p>Un autre outil que vous pouvez trouver utile pour
déboguer est « <b>strace</b> » , qui affiche les
appels systèmes que le processus lance. Il possède
d'autres caractéristiques telles que donner les chemins
d'accès où ont été compilés les
binaires, donner les temps passés dans chacun des appels
systèmes, et il vous permet également de
connaître les résultats des appels. La dernière
version de strace (actuellement la version 3.0.8) peut être
trouvée sur <a href=
"ftp://ftp.std.com/pub/jrs/">ftp://ftp.std.com/pub/jrs/</a>.</p>
<h3>Programmes en tâche de fond (démon)</h3>
<p>Les démons lancent typiquement un <code>fork()</code>
dès leur lancement et terminent donc le père. Cela
fait une session de déboguage très courte.</p>
<p>La manière la plus simple de résoudre ce
problème est de poser un point d'arrêt sur
<code>fork</code>, et lorsque le programme s'arrête, forcer
le retour à 0.</p>
<blockquote>
<pre>
<code>(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 }
</code>
</pre></blockquote>
<h3>Fichiers core</h3>
<p>Lorsque Linux se lance, il n'est généralement pas
configuré pour produire des fichiers core. Si vous les
voulez vous devez utiliser votre shell pour ça en faisant
sous csh (ou tcsh) :</p>
<blockquote>
<pre>
<code>% limit core unlimited
</code>
</pre></blockquote>
avec sh, bash, zsh, pdksh, utilisez
<blockquote>
<pre>
<code>$ ulimit -c unlimited
</code>
</pre></blockquote>
<p>Si vous voulez pousser le vice à nommer votre fichier
core (par exemple si vous utilisez un débogueur
bogué... ce qui est un comble) vous pouvez simplement
modifier le noyau. Editez les fichiers
<code>fs/binfmt_aout.c</code> et <code>fs/binfmt_elf.c</code> (dans
les nouveaux noyaux, vous devrez chercher ailleurs) :</p>
<blockquote>
<pre>
<code> memcpy(corefile,"core.",5);
#if 0
memcpy(corefile+5,current->comm,sizeof(current->comm));
#else
corefile[4] = '\0';
#endif
</code>
</pre></blockquote>
<p>et changez les <code>0</code> par des <code>1</code>.</p>
<h2><a name="ss5.3">5.3 Caractéristiques du
programme</a></h2>
<p>Il est possible d'examiner un peu le programme pour savoir quels
sont les appels de fonctions qui sont effectués le plus
souvent ou bien qui prennent du temps. C'est une bonne
manière d'optimiser le code en déterminant là
où l'on passe le plus de temps. Vous devez compiler tous les
objets avec l'option <code>-p</code>, et pour mettre en forme la
sortie écran, vous aurez besoin du programme
<code>gprof</code> (situé dans les <code>binutils</code>).
Consultez les pages de manuel <code>gprof</code> pour plus de
détails.</p>
<h2><a name="s6">6. Edition de liens</a></h2>
<p>Entre les deux formats de binaires incompatibles,
bibliothèques statiques et dynamiques, on peut comparer
l'opération d'édition de lien en fait à 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>
<p>Pour dissiper la confusion qui règne, nous allons nous
baser sur ce qui se passe lors d'exécution d'un programme,
avec le chargement dynamique. Vous verrez également la
description de l'édition de liens dynamiques, mais plus
tard. Cette section est dédiée à
l'édition de liens qui intervient à la fin de la
compilation.</p>
<h2><a name="ss6.1">6.1 Bibliothèques partagées
contre bibliothèques statiques</a></h2>
<p>La dernière phase de construction d'un programme est de
réaliser l'édition de liens, ce qui consiste à
assembler tous les morceaux du programme et de chercher ceux qui
sont manquants. Bien évidement, beaucoup de programmes
réalisent les mêmes opérations comme ouvrir des
fichiers par exemple, et ces pièces qui réalisent ce
genre d'opérations sont fournies sous la forme de
bibliothèques. Sous Linux, ces bibliothèques peuvent
être trouvées dans les répertoires
<code>/lib</code> et<code>/usr/lib/</code> entre autres.</p>
<p><a name="index.65"></a> <a name="index.66"></a></p>
<p>Lorsque vous utilisez une bibliothèque statique,
l'éditeur de liens cherche le code dont votre programme a
besoin et en effectue une copie dans le programme physique
généré. Pour les bibliothèques
partagées, c'est le contraire : l'éditeur de liens
laisse du code qui lors du lancement du programme chargera
automatiquement la bibliothèque. Il est évident que
ces bibliothèques permettent d'obtenir un exécutable
plus petit; elles permettent également d'utiliser moins de
mémoire et moins de place disque. Linux effectue par
défaut une édition de liens dynamique s'il peut
trouver les bibliothèques de ce type sinon, il effectue une
édition de liens statique. Si vous obtenez des binaires
statiques alors que vous les voulez dynamiques vérifiez que
les bibliothèques existent (<code>*.sa</code> pour le format
a.out, et <code>*.so</code> pour le format ELF) et que vous
possédez les droits suffisants pour y accéder
(lecture).</p>
<p>Sous Linux, les bibliothèques statiques ont pour nom
<code>libnom.a</code>, alors que les bibliothèques
dynamiques sont appelées <code>libnnom.so.x.y.z</code>
où <code>x.y.z</code> représente le numéro de
version. Les bibliothèques dynamiques ont souvent des liens
logiques qui pointent dessus, et qui sont très importants.
Normalement, les bibliothèques standards sont livrées
sous la double forme dynamique et statique.</p>
<p>Vous pouvez savoir de quelles bibliothèques dynamiques un
programme a besoin en utilisant la commande <code>ldd</code>
(<em>List Dynamic Dependencies</em>)</p>
<blockquote>
<pre>
<code>$ ldd /usr/bin/lynx
libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
libc.so.5 => /lib/libc.so.5.2.18
</code>
</pre></blockquote>
<p>Cela indique sur mon système que l'outil
<code>lynx</code> (outil WWW) a besoin des bibliothèques
dynamiques <code>libc.so.5</code> (la bibliothèque C) et de
<code>libncurses.so.1</code> (nécessaire pour le
contrôle du terminal). Si un programme ne possède pas
de dépendances, <code>ldd</code> indiquera `<em>statically
linked</em>' (édition de liens statique).</p>
<h2><a name="index.69"></a> <a name="index.68"></a> <a name=
"index.67"></a> <a name="ss6.2">6.2 A la recherche des fonctions...
ou dans quelle bibliothèque se trouve la fonction
<code>sin()</code> ?')</a></h2>
<p><code>nm</code> <em>nomdebibliothèque</em> vous donne
tous les symboles référencés dans la
bibliothèque. Cela fonctionne que cela soit du code statique
ou dynamique. Supposez que vous vouliez savoir où se trouve
définie la fonction <code>tcgetattr()</code> :</p>
<blockquote>
<pre>
<code>$ nm libncurses.so.1 |grep tcget
U tcgetattr
</code>
</pre></blockquote>
<p>La lettre <code>U</code> vous indique que c'est indéfini
(<em>Undefined</em>) --- cela indique que la bibliothèque
ncurses l'utilise mais ne la définit pas. Vous pouvez
également faire :</p>
<blockquote>
<pre>
<code>$ nm libc.so.5 | grep tcget
00010fe8 T __tcgetattr
00010fe8 W tcgetattr
00068718 T tcgetpgrp
</code>
</pre></blockquote>
<p>La lettre `<code>W</code>' indique que le symbole est
défini mais de telle manière qu'il peut être
surchargé par une autre définition de la fonction
dans une autre bibliothèque (W pour <em>weak</em> : faible).
Une définition normale est marquée par la lettre
`<code>T</code>' (comme pour <code>tcgetpgrp</code>).</p>
<p><a name="index.70"></a></p>
<p>La réponse à la question située dans le
titre est <code>libm.(so|a)</code>. Toutes les fonctions
définies dans le fichier d'en-tête
<code><math.h></code> sont implémentées dans la
bibliothèque mathématique donc vous devrez effectuer
l'édition de liens grâce à
<code>-lm</code>.</p>
<h2><a name="ss6.3">6.3 Trouver les fichiers</a></h2>
<p>Supposons que vous ayez le message d'erreur suivant de la part
de l'éditeur de liens :</p>
<p><code>ld: Output file requires shared library
`libfoo.so.1`</code></p>
<p>La stratégie de recherche de fichiers de ld ou de ses
copains diffère de la version utilisée, mais vous
pouvez être sûr que les fichiers situés dans le
répertoire <code>/usr/lib</code> seront trouvés. Si
vous désirez que des fichiers situés à un
endroit différent soient trouvés, il est
préférable d'ajouter l'option <code>-L</code>
à gcc ou ld.</p>
<p>Si cela ne vous aide pas clairement, vérifiez que vous
avez le bon fichier à l'endroit spécifié. Pour
un système a.out, effectuer l'édition de liens avec
<code>-ltruc</code> implique que ld recherche les
bibliothèques <code>libtruc.sa</code> (bibliothèques
partagées), et si elle n'existe pas, il recherche
<code>libtruc.a</code> (statique). Pour le format ELF, il cherche
<code>libtruc.so</code> puis <code>libtruc.a</code>.
<code>libtruc.so</code> est généralement un lien
symbolique vers <code>libtruc.so.x</code>.</p>
<h2><a name="ss6.4">6.4 Compiler votre propre
bibliothèque</a></h2>
<h3>Numéro de la version</h3>
<p>Comme tout programme, les bibliothèques ont tendance
à avoir quelques bogues qui sont corrigés au fur et
à mesure. De nouvelles fonctionnalités sont
ajoutées et qui peuvent changer l'effet de celles qui
existent ou bien certaines anciennes peuvent êtres
supprimées. Cela peut être un problème pour les
programmes qui les utilisent.</p>
<p>Donc, nous introduisons la notion de numéro de version.
Nous répertorions les modifications effectuées dans
la bibliothèques comme étant soit mineures soit
majeures. Cela signifie qu'une modification mineure ne peut pas
modifier le fonctionnement d'un programme (en bref, il continue
à fonctionner comme avant). Vous pouvez identifier le
numéro de la version de la bibliothèque en regardant
son nom (en fait c'est un mensonge pour les bibliothèques
ELF... mais continuez à faire comme si !) :
<code>libtruc.so.1.2</code> a pour version majeure 1 et mineure 2.
Le numéro de version mineur peut être plus ou moins
élevé --- la bibliothèque C met un
numéro de patch, ce qui produit un nom tel que
<code>libc.so.5.2.18</code>, et c'est également courant d'y
trouver des lettres ou des blancs soulignés ou tout autre
caractère ASCII affichable.</p>
<p>Une des principales différences entre les formats ELF et
a.out se trouve dans la manière de construire la
bibliothèque partagée. Nous traiterons les
bibliothèques partagées en premier car c'est plus
simple.</p>
<h3><a name="index.71"></a> ELF, qu'est-ce que c'est ?</h3>
<p>ELF (<em>Executable and Linking Format</em>) est format de
binaire initialement conçu et développé par
USL (<em>UNIX System Laboratories</em>) et utilisé dans les
systèmes Solaris et System R4. En raison de sa
facilité d'utilisation par rapport à l'ancien format
dit a.out qu'utilisait Linux, les développeurs de GCC et de
la bibliothèque C ont décidé l'année
dernière de basculer tout le système sous le format
ELF. ELF est désormais le format binaire standard sous
Linux.</p>
<h3>ELF, le retour !</h3>
<p>Ce paragraphe provient du groupe
'/news-archives/comp.sys.sun.misc'.</p>
<blockquote>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ù il est extensible. ELF voit un fichier
objet comme une longue liste de sections (plutôt qu'un
tableau de taille fixe d'éléments). Ces sections,
à la différence de COFF ne se trouvent pas à
un endroit constant et ne sont pas dans un ordre particulier, etc.
Les utilisateurs peuvent ajouter une nouvelle section à ces
fichiers objets s'il désirent y mettre de nouvelles
données. ELS possède un format de débogage
plus puissant appelé DWARF (<em>Debugging With Attribute
Record Format</em>) - par encore entièrement
géré par Linux (mais on y travaille !). Une liste
chaînée de « DWARF DIEs » (ou
<em>Debugging Information Entries</em> - NdT... le lecteur aura
sûrement noté 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 écrits sous la forme d'un arbre de
données. Les DIEs peuvent contenir une plus grande
quantité d'information que la section <em>.debug</em> du
format COFF ne le pouvait (un peu comme les graphes
d'héritages du C++).</blockquote>
<blockquote>Les fichiers ELF sont accessibles grâce à
la bibliothèque d'accès de SVR4 (Solaris 2.0
peut-être ?), qui fournit une interface simple et rapide aux
parties les plus complexes d'ELF. Une des aubaines que permet la
bibliothèque d'accès ELF est que vous n'avez jamais
besoin de connaître les méandres du format ELF. Pour
accéder à un fichier Unix, on utilise un Elf *,
retourné par un appel à elf_open(). Ensuite, vous
effectuez des appels à elf_foobar() pour obtenir les
différents composants au lieu d'avoir à triturer le
fichier physique sur le disque (chose que beaucoup d'utilisateurs
de COFF ont fait...).</blockquote>
<p>Les arguments pour ou contre ELF, et les problèmes
liés à la mise à jour d'un système
a.out vers un système ELF sont décrits dans le
ELF-HOWTO et je ne veux pas effectuer de copier coller ici (NdT: ce
HowTo est également traduit en français). Ce HowTo se
trouve au même endroit que les autres.</p>
<h3>Les bibliothèque partagées ELF</h3>
<p>Pour construire <code>libtruc.so</code> comme une
bibliothèque dynamique, il suffit de suivre les
étapes suivantes :</p>
<blockquote>
<pre>
<code>$ 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
</code>
</pre></blockquote>
<p>Cela va générer une bibliothèque
partagée appelée <code>libtruc.so.1.0</code>, les
liens appropriés pour ld (<code>libtruc.so</code>) et le
chargeur dynamique (<code>libtruc.so.1</code>) pour le trouver.
Pour tester, nous ajoutons le répertoire actuel à la
variable d'environnement <code>LD_LIBRARY_PATH</code>.</p>
<p><a name="index.72"></a></p>
<p>Lorsque vous êtes satisfait et que la bibliothèque
fonctionne, vous n'avez plus qu'à la déplacer dans le
répertoire par exemple, <code>/usr/local/lib</code>, et de
recréer les liens appropriés. Le lien de
<code>libtruc.so.1</code> sur <code>libtruc.so.1.0</code> est
enregistré par <code>ldconfig</code>, qui sur bon nombre de
systèmes est lancé lors du processus
d'amorçage. Le lien <code>libfoo.so</code> doit être
mis à jour à la main. Si vous faites attention lors
de la mise à jour de la bibliothèque la chose la plus
simple à réaliser est de créer le lien
<code>libfoo.so -> libfoo.so.1</code>, pour que ldconfig
conserve les liens actuels. Si vous ne faites pas cela, vous aurez
des problèmes plus tard. Ne me dites pas que l'on ne vous a
pas prévenu !</p>
<blockquote>
<pre>
<code>$ /bin/su
# cp libtruc.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libtruc.so.1 libtruc.so )
</code>
</pre></blockquote>
<h3><a name="index.74"></a> <a name="index.73"></a> Les
numéros de version, les noms et les liens</h3>
<p>Chaque bibliothèque possède un nom propre
(<em>soname</em>). Lorsque l'éditeur de liens en trouve un
qui correspond à un nom cherché, il enregistre le nom
de la bibliothèque dans le code binaire au lieu d'y mettre
le nom du fichier de la bibliothèque. Lors de
l'exécution, le chargeur dynamique va alors chercher un
fichier ayant pour nom le nom propre de la bibliothèque, et
pas le nom du fichier de la bibliothèque. Par exemple, une
bibliothèque ayant pour nom <code>libtruc.so</code> peut
avoir comme nom propre <code>libbar.so</code>, et tous les
programmes liés avec vont alors chercher
<code>libbar.so</code> lors de leur exécution.</p>
<p>Cela semble être une nuance un peu pointilleuse mais c'est
la clef de la compréhension de la coexistence de plusieurs
versions différentes de la même bibliothèque
sur le même système. On a pour habitude sous Linux
d'appeler une bibliothèque <code>libtruc.so.1.2</code> par
exemple, et de lui donner comme nom propre
<code>libtruc.so.1</code>. Si cette bibliothèque est
rajoutée dans un répertoire standard (par exemple
dans <code>/usr/lib</code>), le programme <code>ldconfig</code> va
créer un lien symbolique entre <code>libtruc.so.1 ->
libtruc.so.1.2</code> pour que l'image appropriée soit
trouvée lors de l'exécution. Vous aurez
également besoin d'un lien symbolique <code>libtruc.so ->
libtruc.so.1</code> pour que ld trouve le nom propre lors de
l'édition de liens.</p>
<p>Donc, lorsque vous corrigez des erreurs dans la
bibliothèque ou bien lorsque vous ajoutez de nouvelles
fonctions (en fait, pour toute modification qui n'affecte pas
l'exécution des programmes déjà existants),
vous reconstruisez la bibliothèque, conservez le nom propre
tel qu'il était et changez le nom du fichier. Lorsque vous
effectuez des modifications que peuvent modifier le
déroulement des programmes existants, vous pouvez tout
simplement incrémenter le nombre situé dans le nom
propre --- dans ce cas, appelez la nouvelle version de la
bibliothèque <code>libtruc.so.2.0</code>, et donnez-lui
comme nom propre <code>libtruc.so.2</code>. Maintenant, faites
pointer le lien de <code>libfoo.so</code> vers la nouvelle version
et tout est bien dans le meilleur des mondes !</p>
<p>Il est utile de remarquer que vous n'êtes pas
obligé de nommer les bibliothèques de cette
manière, mais c'est une bonne convention. Elf vous donne une
certaine liberté pour nommer des bibliothèques tant
et si bien que cela peut perturber certains utilisateurs, mais cela
ne veut pas dire que vous êtes obligé de le faire.</p>
<p>Résumé : supposons que choisissiez d'adopter la
méthode traditionnelle avec les mises à jour majeures
qui peuvent ne pas être compatibles avec les versions
précédentes et les mises à jour mineures qui
ne posent pas ce problème. Il suffit de créer la
bibliothèque de cette manière :</p>
<blockquote>
<pre>
<code>gcc -shared -Wl,-soname,libtruc.so.majeur -o libtruc.so.majeur.mineur
</code>
</pre></blockquote>
et tout devrait être parfait !
<h3>a.out. Le bon vieux format</h3>
<p>La facilité de construire des bibliothèque
partagées est la raison principale de passer à ELF.
Ceci dit, il est toujours possible de créer des
bibliothèques dynamiques au format a.out.
Récupérez le fichier archive <a href=
"ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz">
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz</a>
et lisez les 20 pages de documentation que vous trouverez dedans
après l'avoir désarchivé. Je n'aime pas avoir
l'air d'être aussi partisan, mais il est clair que je n'ai
jamais aimé ce format :-).</p>
<h3><a name="index.76"></a> <a name="index.75"></a> ZMAGIC contre
QMAGIC</h3>
<p>QMAGIC est le format des exécutables qui ressemble un peu
aux vieux binaires a.out (également connu comme ZMAGIC),
mais qui laisse la première page libre. Cela permet plus
facilement de récupérer les adresses non
affectées (comme NULL) dans l'intervalle 0-4096 (NdT : Linux
utilise des pages de 4Ko).</p>
<p>Les éditeurs de liens désuets ne gèrent que
le format ZMAGIC, ceux un peu moins rustiques gèrent les
deux, et les plus récents uniquement le QMAGIC. Cela importe
peu car le noyau gère les deux types.</p>
<p>La commande <code>file</code> est capable d'identifier si un
programme est de type QMAGIC.</p>
<h3>Gestion des fichiers</h3>
<p>Une bibliothèque dynamique a.out (DLL) est
composée de deux fichiers et d'un lien symbolique. Supposons
que l'on utilise la bibliothèque <em>truc</em>, les fichiers
seraient les suivants : <code>libtruc.sa</code> et
<code>libtruc.so.1.2</code>; et le lien symbolique aurait pour nom
<code>libtruc.so.1</code> et pointerait sur le dernier des
fichiers. Mais à quoi servent-ils ?</p>
<p>Lors de la compilation, <code>ld</code> cherche
<code>libtruc.sa</code>. C'est le fichier de description de la
bibliothèque : il contient toutes les données
exportées et les pointeurs vers les fonctions
nécessaires pour l'édition de liens.</p>
<p>Lors de l'exécution, le chargeur dynamique cherche
<code>libtruc.so.1</code>. C'est un lien symbolique plutôt
qu'un réel fichier pour que les bibliothèques
puissent être mise à jour sans avoir à casser
les applications qui utilisent la bibliothèque. Après
la mise à jour, disons que l'on est passé à la
version <code>libfoo.so.1.3</code>, le lancement de ldconfig va
positionner le lien. Comme cette opération est atomique,
aucune application fonctionnant n'aura de problème.</p>
<p>Les bibliothèques DLL (Je sais que c'est une
tautologie... mais pardon !) semblent être très
souvent plus importantes que leur équivalent statique. En
fait, c'est qu'elles réservent de la place pour les
extensions ultérieures sous la simple forme de trous qui
sont fait de telle manière qu'ils n'occupent pas de place
disque (NdT : un peu comme les fichiers <code>core</code>).
Toutefois, un simple appel à <code>cp</code> ou à
<code>makehole</code> les remplira... Vous pouvez effectuer une
opération de <code>strip</code> après la construction
de la bibliothèque, comme les adresses sont à des
endroits fixes. <b>Ne faites pas la même opération
avec les bibliothèques ELF !</b></p>
<h3>« libc-lite » ?</h3>
<p>Une « libc-lite » (contraction de <em>libc</em> et
<em>little</em>) est une version épurée et
réduite de la bibliothèque libc construite de telle
manière qu'elle puisse tenir sur une disquette avec un
certain nombre d'outil Unix. Elle n'inclut pas curses, dbm,
termcap, ... Si votre <code>/lib/libc.so.4</code> est liée
avec une bibliothèque de ce genre il est très
fortement conseillé de la remplacer avec une version
complète.</p>
<h3>Edition de liens : problème courants</h3>
<p>Envoyez-les moi !</p>
<dl>
<dt><b>Des programmes statiques lorsque vous les voulez
partagés</b></dt>
<dd>
<p><a name="index.77"></a> <a name="index.78"></a></p>
<p>Vérifiez que vous avez les bons liens pour que
<code>ld</code> puisse trouver les bibliothèques
partagées. Pour ELF cela veut dire que
<code>libtruc.so</code> est un lien symbolique sur son image, pour
a.out un fichier <code>libtruc.sa</code>. Beaucoup de personnes ont
eu ce problème après être passés des
outils ELF 2.5 à 2.6 (<code>binutils</code>) --- la
dernière version effectue une recherche plus intelligente
pour les bibliothèques dynamiques et donc ils n'avaient pas
créé tous les liens symboliques nécessaires.
Cette caractéristique avait été
supprimée pour des raisons de compatibilité avec
d'autres architectures et parce qu'assez souvent cela ne marchait
pas bien. En bref, cela posait plus de problèmes qu'autre
chose.</p>
</dd>
<dt><b>Le programme `mkimage' n'arrive pas à trouver
libgcc</b></dt>
<dd>
<p><a name="index.79"></a></p>
<p>Comme <code>libc.so.4.5.x</code> et suivantes, libgcc n'est pas
une bibliothèque partagée. Vous devez remplacer les
`<code>-lgcc</code>' sur la ligne de commande par <code>`gcc
-print-libgcc-file-name`</code> (entre quotes)</p>
<p>Egalement, détruisez tous les fichiers situés dans
<code>/usr/lib/libgcc*</code>. C'est important.</p>
</dd>
<dt><b>Le message <code>__NEEDS_SHRLIB_libc_4 multiply
defined</code></b></dt>
<dd>
<p>Sont une conséquence du même problème.</p>
</dd>
<dt><b>Le message ``Assertion failure'' apparaît lorsque vous
reconstruisez une DLL</b></dt>
<dd>
<p>Ce message énigmatique signifie qu'un
élément de votre table <em>jump</em> a
dépassé la table car trop peu de place était
réservée dans le fichier <code>jump.vars</code> file.
Vous pouvez trouver le(s) coupable(s) en lançant la commande
<code>getsize</code> fournie dans le paquetage tools-2.17.tar.gz.
La seule solution est de passer à une nouvelle version
majeure, même si elle sera incompatible avec les
précédentes.</p>
</dd>
<dt><b><code>ld: output file needs shared library
libc.so.4</code></b></dt>
<dd>
<p>Cela arrive lorsque vous effectuez l'édition de liens
avec des bibliothèques différentes de la libc (comme
les bibliothèques X) et que vous utilisez l'option
<code>-g</code> sans utiliser l'option <code>-static</code>.</p>
<p>Les fichiers <code>.sa</code> pour les bibliothèques
dynamiques ont un symbole non résolu
<code>_NEEDS_SHRLIB_libc_4</code> qui est défini dans
<code>libc.sa</code>. Or, lorsque vous utilisez <code>-g</code>
vous faites l'édition de liens avec <code>libg.a</code> ou
<code>libc.a</code> et donc ce symbole n'est jamais
défini.</p>
<p>Donc, pour résoudre le problème, ajoutez l'option
<code>-static</code> lorsque vous compilez avec l'option
<code>-g</code>, ou n'utilisez pas <code>-g</code> lors de
l'édition de liens !</p>
</dd>
</dl>
<h2><a name="s7">7. Chargement dynamique</a></h2>
<p><em>Ce paragraphe est en fait un peu court : il sera
étendu dans une version ultérieure dès que
j'aurai récupéré le HowTo ELF</em></p>
<h2><a name="ss7.1">7.1 Concepts</a></h2>
<p>Linux possède des bibliothèques dynamiques, comme
on vous le répète depuis le début de ce
document ! Or, il existe un système pour reporter le travail
d'association des noms des symboles et de leur adresse dans la
bibliothèque, qui est normalement effectué lors de
l'édition de liens en l'effectuant lors du chargement du
programme.</p>
<h2><a name="ss7.2">7.2 Messages d'erreur</a></h2>
<p>Envoyez moi vos erreurs ! Je n'en fait pas grand chose sauf les
insérer dans ce paragraphe...</p>
<dl>
<dt><b><code>can't load library: /lib/libxxx.so, Incompatible
version</code></b></dt>
<dd>
<p>(seulement a.out) Cela signifie que vous n'avez pas la version
correcte de la bibliothèque (numéro dit majeur). Non,
il n'est pas possible d'effectuer un lien symbolique sur la
bibliothèque que vous possédez : si vous avez de la
chance, vous obtiendrez un <em>segmentation fault</em>.
Récupérez la nouvelle version. Un message un peu
équivalent existe également sur les systèmes
ELF :</p>
<blockquote>
<pre>
<code>ftp: can't load library 'libreadline.so.2'
</code>
</pre></blockquote>
</dd>
<dt><b><code>warning using incompatible library version
xxx</code></b></dt>
<dd>
<p>(seulement a.out) Vous avez un numéro de version de
bibliothèque (mineur) inférieur à la version
avec laquelle a été compilé le programme. Le
programme fonctionnera sûrement. Une mise à jour est
toutefois conseillée.</p>
</dd>
</dl>
<h2><a name="index.81"></a> <a name="index.80"></a> <a name=
"ss7.3">7.3 Contrôler l'opération de chargement
dynamique</a></h2>
<p>Il existe certaines variables d'environnements que le chargeur
dynamique utilise. Beaucoup sont exploitées par le programme
<code>ldd</code> lorsqu'il s'agit de particularités de
l'environnement de l'utilisateur, ce qui peuvent être
positionnées pour lancer ldd avec des options
particulières. Voici une description des différentes
variables d'environnement que vous pouvez rencontrer :</p>
<ul>
<li><code>LD_BIND_NOW</code> --- normalement, les fonctions ne sont
pas cherchées dans les bibliothèques avant leur
appel. En positionnant cette option, vous vérifiez que
toutes les fonctions employées dans votre programmes se
trouvent bien dans la bibliothèque lors de son chargement,
ce qui ralentit le lancement du programme. C'est utile lorsque vous
voulez tester que l'édition de liens s'est parfaitement
déroulée et que tous les symboles sont bien
associés.</li>
<li><code>LD_PRELOAD</code> peut être défini avec un
nom de fichier qui contient des fonctions surchargeant des
fonctions déjà existantes. Par exemple, si vous
testez une stratégie d'allocation mémoire, et que
vous voulez remplacer le malloc de la bibliothèque C par le
vôtre situé dans un module ayant pour nom
<code>malloc.o</code>, il vous suffit de faire :
<blockquote>
<pre>
<code>$ export LD_PRELOAD=malloc.o
$ test_mon_malloc
</code>
</pre></blockquote>
<code>LD_ELF_PRELOAD</code> et <code>LD_AOUT_PRELOAD</code> sont
similaires, mais leur utilisation est spécifique au type de
binaire utilisé. Si
<code>LD_</code><em>TypeBinaire</em><code>_PRELOAD</code> et
<code>LD_PRELOAD</code> sont positionnés, celui
correspondant le mieux à la machine est utilisé.</li>
<li><code>LD_LIBRARY_PATH</code> contient une liste de
répertoires contenant les bibliothèques dynamiques.
Cela n'affecte pas l'édition de liens : cela n'a qu'un effet
lors de l'exécution. Il faut noter qu'elle est
désactivée pour des programmes qui s'exécutent
avec un setuid ou un setgid. Enfin,
<code>LD_ELF_LIBRARY_PATH</code> et
<code>LD_AOUT_LIBRARY_PATH</code> peuvent être
utilisés pour orienter le mode de compilation du binaire.
<code>LD_LIBRARY_PATH</code> ne devrait pas être
nécessaire en principe : ajoutez les répertoires dans
le fichier <code>/etc/ld.so.conf/</code> et relancez ldconfig.</li>
<li><code>LD_NOWARN</code> s'applique au format a.out uniquement.
Lorsqu'elle est positionnée (c.a.d si elle existe par
exemple avec <code>LD_NOWARN=true; export LD_NOWARN</code>) cela
arrête le chargeur du programme même sur des
avertissements insignifiants (tels que des messages
d'incompatibilités de numéros mineurs de
version).</li>
<li><code>LD_WARN</code> s'applique à ELF uniquement.
Lorsqu'elle est positionnée, on transforme le message
habituellement fatal <em>Can't find library</em> en un
avertissement. Ce n'est pas positionné par défaut
mais c'est important pour un programme comme ldd.</li>
<li><code>LD_TRACE_LOADED_OBJECTS</code> s'applique à ELF
uniquement, et permet de simuler l'exécution des programmes
comme s'ils l'étaient par <code>ldd</code> :
<blockquote>
<pre>
<code>$ 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
</code>
</pre></blockquote>
</li>
</ul>
<h2><a name="index.83"></a> <a name="index.82"></a> <a name=
"ss7.4">7.4 Ecrire des programmes en utilisant le chargement
dynamique</a></h2>
<p>Cela ressemble énormément au système de
chargement dynamique utilisé sous Solaris 2.x. Ce
système est décrit d'une manière
précise dans le document expliquant la programmation avec
ELF écrit par H J Lu et dans la page de manuel
<code>dlopen(3)</code>, qui se trouve dans le paquetage ld.so.
Voici un exemple simple : pensez à faire l'édition de
liens avec <code>-ldl</code></p>
<blockquote>
<pre>
<code>#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");
}
}
</code>
</pre></blockquote>
<h2><a name="s8">8. Contacter les développeurs</a></h2>
<h2><a name="index.84"></a> <a name="ss8.1">8.1 Annoncer des
bogues</a></h2>
<p>Commencez par mettre en doute le problème. Est-ce
spécifique à Linux ou bien cela arrive avec gcc mais
sur d'autres plates-formes ? Est-ce spécifique à la
version du noyau ? A la version de la bibliothèque C ?
Est-ce que ce problème disparaît lorsque vous
effectuez une édition de liens statique ? Pouvez-vous
produire un code très court mettant en évidence le
problème ?</p>
<p>Après avoir répondu après ces quelques
questions, vous saurez quel programme est à l'origine du
problème. Pour un problème direct avec GCC, le mieux
est de consulter le fichier d'information livré avec : la
procédure pour rapporter un bogue y est
détaillé. Pour un problème avec ld.so, la
bibliothèque C ou mathématique, envoyez un courrier
électronique à
<code>linux-gcc@vger.rutgers.edu</code>. Si possible, donnez un
court exemple mettant en évidence le problème ainsi
qu'une courte description indiquant ce que le programme aurait
normalement dû faire, et ce qu'il fait en
réalité.</p>
<h2><a name="ss8.2">8.2 Participer au développement</a></h2>
<p>Si vous désirez participer au développement de GCC
ou de la bibliothèque C, la première chose à
faire est de rejoindre la liste de diffusion
<code>linux-gcc@vger.rutgers.edu</code>. Si vous désirez
uniquement savoir de quoi ça parle, il existe des archives
à l'adresse <a href=
"http://homer.ncm.com/linux-gcc/">http://homer.ncm.com/linux-gcc/</a>.
Tout dépend de ce que vous désirez faire ou apporter
à ce projet !</p>
<h2><a name="s9">9. Divers</a></h2>
<h2><a name="ss9.1">9.1 Ce document</a></h2>
<p>Ce HowTo est basé sur la FAQ de Mitchum DSouza's. Bon
nombre des informations en proviennent. D'une manière
générale, il est fréquent de dire une phrase
du genre « je n'ai pas tout testé et donc ne me
blâmez pas si vous cassez votre disque, votre système
ou si vous rompez avec votre épouse ».</p>
<p>Le nom des contributeurs à ce document sont donnés
par ordre alphabé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ûr Linus Torvalds,
sans qui ce genre d'exercice aurait été difficile,
voir impossible :-)</p>
<p>Ne soyez pas offensé si votre nom n'apparaît pas
dans la liste et que vous ayez contribué à ce
document (sous la forme d'un HowTo ou d'une FAQ). Envoyez-moi un
courrier électronique et j'effectuerai la correction.</p>
<h2><a name="ss9.2">9.2 Traduction</a></h2>
<p>A l'heure ou j'écris ces lignes, je ne connais pas de
traduction de ce document. Si vous en réalisez une, s'il
vous plaît dites-le moi. Je suis disponible pour toute aide
concernant l'explication du texte, je serai très content d'y
répondre.</p>
<p>Note du traducteur : <b>Cocorico !</b> La version
française est la première traduction de ce
document.</p>
<h2><a name="ss9.3">9.3 Contacts</a></h2>
<p>Tout contact est le bienvenu. Envoyez-moi un courrier
électronique à l'adresse suivante : <a href=
"mailto:dan@detached.demon.co.uk">dan@detached.demon.co.uk</a>. Ma
clef publique PGP (ID 5F263625) est disponible sur mes <a href=
"http://ftp.linux.org.uk/~barlow/">pages WWW</a>, Si vous souhaitez
rendre confidentiel certains messages.</p>
<h2><a name="ss9.4">9.4 Copyright</a></h2>
<p>Toutes les remarques appartiennent à leurs auteurs
respectifs.</p>
<p>Ce document est copyrighté (C) 1996 Daniel Barlow
<code><dan@detached.demon.co.uk></code>. Il peut être
reproduit et distribué en partie ou entièrement, sur
tout support physique ou électronique, du moment où
ce copyright se trouve sur toute les copies. La redistribution
commerciale est autorisée et encouragée. Toutefois
l'auteur de ce document doit être mis au courant de ce genre
de distributions.</p>
<p>Toute traduction, adaptation, ou bien tout travail incorporant
tout document HowTo Linux doit posséder ce copyright. De
cette manière, vous ne pouvez pas imposer de restriction
à la distribution de ce document. Des exceptions peuvent
être éventuellement accordées sous certaines
conditions : contactez le coordinateur des HowTo's Linux à
l'adresse donnée ci-dessous.</p>
<p>En résumé, nous souhaitons voir diffuser
l'information de la manière la plus large qui soit.
Toutefois, nous souhaitons garder la maîtrise de ces
documents et nous aimerions être consultés avant toute
diffusion des HowTo's.</p>
<p>Si vous avez des questions, vous pouvez contacter Greg Hankins,
le coordinateur des HowTo Linux HOWTO à l'adresse
électronique suivante :
<code>gregh@sunsite.unc.edu</code></p>
<h2><a name="s10">10. Index</a></h2>
<p>Les entrées de cet index sont triées dans l'ordre
alphabétique.</p>
<ul>
<li><code>-fwritable-strings</code> <a href="#index.39">39</a>,
<a href="#index.56">56</a></li>
<li>/lib/cpp <a href="#index.16">16</a></li>
<li>a.out <a href="#index.1">1</a></li>
<li><code>ar</code> <a href="#index.10">10</a></li>
<li><code>as</code> <a href="#index.8">8</a></li>
<li><asm/*.h> <a href="#index.19">19</a></li>
<li><code>atoi()</code> <a href="#index.40">40</a></li>
<li><code>atol()</code> <a href="#index.41">41</a></li>
<li>exécutables trop gros <a href="#index.63">63</a>,
<a href="#index.65">65</a>, <a href="#index.77">77</a></li>
<li>chewing gum <a href="#index.3">3</a></li>
<li><code>cos()</code> <a href="#index.68">68</a></li>
<li>deboguer <a href="#index.59">59</a></li>
<li>divers <a href="#index.72">72</a></li>
<li><code>dlopen()</code> <a href="#index.82">82</a></li>
<li><code>dlsym()</code> <a href="#index.83">83</a></li>
<li>documentation <a href="#index.4">4</a></li>
<li>EINTR <a href="#index.52">52</a></li>
<li>elf <a href="#index.0">0</a>, <a href="#index.71">71</a></li>
<li><code>execl()</code> <a href="#index.57">57</a></li>
<li><code>fcntl</code> <a href="#index.47">47</a></li>
<li><code>FD_CLR</code> <a href="#index.44">44</a></li>
<li><code>FD_ISSET</code> <a href="#index.45">45</a></li>
<li><code>FD_SET</code> <a href="#index.43">43</a></li>
<li><code>FD_ZERO</code> <a href="#index.46">46</a></li>
<li><code>fichier</code> <a href="#index.2">2</a></li>
<li><float.h> <a href="#index.20">20</a></li>
<li>gcc <a href="#index.6">6</a></li>
<li><code>gcc -fomit-frame-pointer</code> <a href=
"#index.61">61</a></li>
<li><code>gcc -g</code> <a href="#index.60">60</a></li>
<li>gcc -v <a href="#index.14">14</a></li>
<li>gcc, bogues <a href="#index.15">15</a>, <a href=
"#index.28">28</a>, <a href="#index.29">29</a>, <a href=
"#index.84">84</a></li>
<li>gcc, options de compilation <a href="#index.13">13</a>,
<a href="#index.25">25</a>, <a href="#index.26">26</a></li>
<li>gdb <a href="#index.64">64</a></li>
<li>fichiers d'en-tête <a href="#index.17">17</a></li>
<li>appels systèmes interrompus <a href=
"#index.51">51</a></li>
<li><code>ld</code> <a href="#index.9">9</a></li>
<li><code>LD_*</code> : variables d'environnement <a href=
"#index.80">80</a></li>
<li>ldd <a href="#index.81">81</a></li>
<li>libc <a href="#index.7">7</a></li>
<li><code>libg.a</code> <a href="#index.62">62</a></li>
<li>libgcc <a href="#index.79">79</a></li>
<li><limits.h> <a href="#index.21">21</a></li>
<li>lint <a href="#index.58">58</a></li>
<li><linux/*.h> <a href="#index.18">18</a></li>
<li><code><math.h></code> <a href="#index.70">70</a></li>
<li>maths <a href="#index.69">69</a></li>
<li><code>mktemp()</code> <a href="#index.55">55</a></li>
<li>numéro de version <a href="#index.12">12</a>, <a href=
"#index.74">74</a></li>
<li>optimisation <a href="#index.27">27</a></li>
<li>pages de manuel <a href="#index.5">5</a></li>
<li>QMAGIC <a href="#index.76">76</a></li>
<li>segmentation fault <a href="#index.30">30</a>, <a href=
"#index.54">54</a></li>
<li>segmentation fault, in GCC <a href="#index.33">33</a></li>
<li>select() <a href="#index.50">50</a></li>
<li><code>SIGBUS</code> <a href="#index.34">34</a></li>
<li><code>SIGEMT</code> <a href="#index.35">35</a></li>
<li><code>SIGIOT</code> <a href="#index.36">36</a></li>
<li>SIGSEGV <a href="#index.31">31</a>, <a href=
"#index.53">53</a></li>
<li>SIGSEGV, in gcc <a href="#index.32">32</a></li>
<li><code>SIGSYS</code> <a href="#index.38">38</a></li>
<li><code>SIGTRAP</code> <a href="#index.37">37</a></li>
<li><code>sin()</code> <a href="#index.67">67</a></li>
<li>soname <a href="#index.73">73</a></li>
<li><code>sprintf()</code> <a href="#index.42">42</a></li>
<li>binaires linkés statiquement <a href="#index.66">66</a>,
<a href="#index.78">78</a></li>
<li><stdarg.h> <a href="#index.23">23</a></li>
<li><stddef.h> <a href="#index.24">24</a></li>
<li><code>strings</code> <a href="#index.11">11</a></li>
<li><code><sys/time.h></code> <a href="#index.48">48</a></li>
<li><code><unistd.h></code> <a href="#index.49">49</a></li>
<li><varargs.h> <a href="#index.22">22</a></li>
<li>ZMAGIC <a href="#index.75">75</a></li>
</ul>
</body>
</html>
|