{"id":1540,"date":"2012-02-04T10:00:38","date_gmt":"2012-02-04T09:00:38","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=1540"},"modified":"2012-02-04T10:00:38","modified_gmt":"2012-02-04T09:00:38","slug":"mise-au-point-de-bibliotheque-dynamique-23","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2012\/02\/04\/mise-au-point-de-bibliotheque-dynamique-23\/","title":{"rendered":"Mise au point de biblioth\u00e8que dynamique (2\/3)"},"content":{"rendered":"<p style=\"text-align: justify;\">(<a title=\"Development of a dynamic library (2\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/02\/04\/development-of-a-dynamic-library-23\/\">English translation<\/a>)<\/p>\n<p style=\"text-align: justify;\">\n<p style=\"text-align: justify;\">Nous avons examin\u00e9 dans l&rsquo;<a title=\"Mise au point de biblioth\u00e8que dynamique (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/mise-au-point-de-bibliotheque-dynamique-1-compilation-versions-et-liens-symboliques\/\" target=\"_blank\">article pr\u00e9c\u00e9dent<\/a> comment compiler une biblioth\u00e8que dynamique et g\u00e9rer correctement ses num\u00e9ros majeurs et mineurs de version afin d&rsquo;en faciliter la maintenance, tant pour le d\u00e9veloppeur (de la biblioth\u00e8que mais aussi pour celui des applications qui l&rsquo;utilisent) que pour l&rsquo;administrateur du syst\u00e8me sur lequel elle est install\u00e9e. Nous allons \u00e0 pr\u00e9sent examiner comment effectuer le d\u00e9bogage de notre bibilioth\u00e8que et des applications qui l&rsquo;appellent.<\/p>\n<p>\n<!--more-->\n<\/p>\n<h1>Suivi des appels<\/h1>\n<p style=\"text-align: justify;\">Le premier utilitaire a conna\u00eetre est <code><strong>ltrace<\/strong><\/code>. Il permet d&rsquo;envoyer vers la sortie d&rsquo;erreur du processus une trace de tous les appels de fonctions de biblioth\u00e8ques dynamiques. Nous nous repla\u00e7ons dans la m\u00eame situation que pour l&rsquo;article pr\u00e9c\u00e9dent avec les r\u00e9pertoires suivants<\/p>\n<ul>\n<li style=\"text-align: justify;\"><code>factorielle\/src<\/code> contient le code source de la biblioth\u00e8que<\/li>\n<li style=\"text-align: justify;\"><code>factorielle\/include<\/code> o\u00f9 se trouvent les fichiers d&rsquo;en-t\u00eate de la biblioth\u00e8que<\/li>\n<li style=\"text-align: justify;\"><code>factorielle\/lib<\/code> contenant la biblioth\u00e8que compil\u00e9e<\/li>\n<li style=\"text-align: justify;\"><code>factorielle\/test<\/code> dans lequel on trouve codes sources et fichiers ex\u00e9cutables des applications appelant la biblioth\u00e8que<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Voici un aper\u00e7u du contenu de notre r\u00e9pertoire<\/p>\n<pre>[~] <strong>cd factorielle<\/strong>\n[factorielle]$ <strong>ls<\/strong>\ninclude  lib  src  test\n[factorielle]$ <strong>ls include\/<\/strong>\n<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.h\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.h\" target=\"_blank\">fact.h<\/a>\n[factorielle]$ <strong>ls -l lib\/<\/strong>\ntotal 8\nlrwxrwxrwx 1 cpb cpb   12 2012-02-04 05:04 libfact.so -&gt; libfact.so.2\nlrwxrwxrwx 1 cpb cpb   14 2012-02-04 05:04 libfact.so.2 -&gt; libfact.so.2.0\n-rwxrwxr-x 1 cpb cpb 6661 2012-02-04 05:04 libfact.so.2.0\n[factorielle]$ <strong>ls src\/<\/strong>\n<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.c\" target=\"_blank\">fact.c<\/a>  fact.o\n[factorielle]$ <strong>ls test\/<\/strong>\ncalcule-factorielle  <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/calcule-factorielle.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/calcule-factorielle.c\" target=\"_blank\">calcule-factorielle.c<\/a>\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Les d\u00e9tails pour cr\u00e9er les fichiers ex\u00e9cutables et les liens symboliques se trouvaient dans <a title=\"Mise au point de biblioth\u00e8que dynamique (1\/3)\" href=\"http:\/\/www.blaess.fr\/christophe\/2012\/01\/28\/mise-au-point-de-bibliotheque-dynamique-1-compilation-versions-et-liens-symboliques\/\" target=\"_blank\">le pr\u00e9c\u00e9dent article<\/a>. Voici \u00e9galement un exemple d&rsquo;ex\u00e9cution du programme de test.<\/p>\n<pre>[factorielle]$ <strong>export LD_LIBRARY_PATH=lib\/<\/strong>\n[factorielle]$ <strong>.\/test\/calcule-factorielle 7<\/strong>\n7! = 5040\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Employons <code>ltrace<\/code> pour observer les appels de fonctions de biblioth\u00e8ques.<\/p>\n<pre>[factorielle]$ <strong>ltrace .\/test\/calcule-factorielle 4 5 6<\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf896624, 0x80486b0, 0x8048720\n__isoc99_sscanf(0xbf89745f, 0x8048796, 0xbf896578, 0x80486d1, 0x8048500) = 1\nfactorielle(4, 0xbf896570, 0xbf896578, 0x80486d1, 0x8048500) = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 4, ...4! = 24\n)     = 8\n__isoc99_sscanf(0xbf897461, 0x8048796, 0xbf896578, 24, 0) = 1\nfactorielle(5, 0xbf896570, 0xbf896578, 24, 0)    = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 5, ...5! = 120\n)     = 9\n__isoc99_sscanf(0xbf897463, 0x8048796, 0xbf896578, 120, 0) = 1\nfactorielle(6, 0xbf896570, 0xbf896578, 120, 0)   = 0\nfprintf(0xb7896500, \"%ld! = %lldn\", 6, ...6! = 720\n)     = 9\n+++ exited (status 0) +++\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Tout d&rsquo;abord il y a un m\u00e9lange \u00e0 l&rsquo;\u00e9cran entre la sortie standard et la sortie d&rsquo;erreur, ce qui rend les comptes-rendus d&rsquo;appel difficiles \u00e0 lire. Envoyons la sortie d&rsquo;erreur dans un fichier.<\/p>\n<pre>[factorielle]$ <strong>ltrace .\/test\/calcule-factorielle 4 5 6 2&gt;traces.txt<\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Si notre processus utilise sa sortie d&rsquo;erreur, on peut demander \u00e0 <code>ltrace<\/code> d&rsquo;envoyer ses messages directement dans un fichier \u00e0 l&rsquo;aide de son option <code>-o<\/code>.<\/p>\n<pre>[factorielle]$ <strong>ltrace -o traces.txt .\/test\/calcule-factorielle 4 5 6 <\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Voyons ce que contient notre fichier de traces.<\/p>\n<pre>[factorielle]$ <strong>cat traces.txt <\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf9384f4, 0x80486b0, 0x8048720 &lt;unfinished ...&gt;\n_isoc99_sscanf(0xbf93a45f, 0x8048796, 0xbf938448, 0x80486d1, 0x8048500)                 = 1\nfactorielle(4, 0xbf938440, 0xbf938448, 0x80486d1, 0x8048500)                            = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 4, ...)                                            = 8\n__isoc99_sscanf(0xbf93a461, 0x8048796, 0xbf938448, 24, 0)                               = 1\nfactorielle(5, 0xbf938440, 0xbf938448, 24, 0)                                           = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 5, ...)                                            = 9\n__isoc99_sscanf(0xbf93a463, 0x8048796, 0xbf938448, 120, 0)                              = 1\nfactorielle(6, 0xbf938440, 0xbf938448, 120, 0)                                          = 0\nfprintf(0xb771d500, \"%ld! = %lldn\", 6, ...)                                            = 9\n+++ exited (status 0) +++\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Nous voyons bien nos appels de la fonction <code>factorielle()<\/code> mais ce qui est curieux, c&rsquo;est que <code>ltrace<\/code> affiche cinq arguments pour notre routine, alors qu&rsquo;elle n&rsquo;en comporte que deux normalement (voir <a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.h\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/fact.h\" target=\"_blank\"><code>fact.h<\/code><\/a>). En fait, <code>ltrace<\/code> s&rsquo;appuie sur un fichier de configuration nomm\u00e9 <code>\/etc\/ltrace.conf<\/code> qui contient le nombre et le type des arguments des fonctions des biblioth\u00e8ques dynamiques du syst\u00e8me. S&rsquo;il ne trouve pas la fonction dans ce fichier, il affiche cinq arguments par d\u00e9faut.<\/p>\n<pre><strong>\/etc\/ltrace.conf<\/strong>\n; ltrace.conf\n;\n; ~\/.ltrace.conf will also be read, if it exists. The -F option may be\n; used to suppress the automatic inclusion of both this file and\n; ~\/.ltrace.conf, and load a different config file or config files\n; instead.\n[...]\n; arpa\/inet.h\nint inet_aton(string,addr);\nstring inet_ntoa(addr);                 ; It isn't an ADDR but an hexa number...\naddr inet_addr(string);\n[...]\n; stdio.h\nint fclose(file);\nint feof(file);\nint ferror(file);\nint fflush(file);\nchar fgetc(file);\naddr fgets(+string, int, file);\nint fileno(file);\nfile fopen(string,string);\nfile fopen64(string,string);\nint fprintf(file,format);\nint fputc(char,file);\nint fputs(string,file);\nulong fread(addr,ulong,ulong,file);\nulong fread_unlocked(addr,ulong,ulong,file);\nulong fwrite(string,ulong,ulong,file);\nulong fwrite_unlocked(string,ulong,ulong,file);\nint pclose(addr);\nvoid perror(string);\naddr popen(string, string);\nint printf(format);\nint puts(string);\nint remove(string);\nint snprintf(+string2,ulong,format);\nint sprintf(+string,format);\n[...]\nint   SYS_waitpid(int,addr,int);\nulong SYS_readv(int,addr,int);\nulong SYS_writev(int,addr,int);\nint   SYS_mprotect(addr,int,int);\nint   SYS_access(string,octal);<\/pre>\n<p style=\"text-align: justify;\">Bien entendu notre fonction ne figure pas dans ce fichier. Nous pourrions le modifier (si la biblioth\u00e8que \u00e9tait install\u00e9e dans un emplacement du syst\u00e8me accessible \u00e0 tous les utilisateurs), mais je propose plut\u00f4t de cr\u00e9er un fichier suppl\u00e9mentaire <code>.ltrace.conf<\/code> que nous pla\u00e7ons dans notre r\u00e9pertoire personnel (<code>ltrace<\/code> vient le chercher \u00e0 cet emplacement).<\/p>\n<pre>[factorielle]$ <strong>cat ~\/<a title=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/ltrace.conf\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2012-02-04\/ltrace.conf\" target=\"_blank\">.ltrace.conf<\/a> <\/strong>\nint factorielle(long,addr);\n[factorielle]$ <strong>ltrace -o traces.txt .\/test\/calcule-factorielle 4 5 6<\/strong>\n4! = 24\n5! = 120\n6! = 720\n[factorielle]$ <strong>cat traces.txt <\/strong>\n__libc_start_main(0x80485b4, 4, 0xbf8b3764, 0x80486b0, 0x8048720\n__isoc99_sscanf(0xbf8b545c, 0x8048796, 0xbf8b36b8, 0x80486d1, 0x8048500)           = 1\nfactorielle(4, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 4, ...)                                       = 8\n__isoc99_sscanf(0xbf8b545e, 0x8048796, 0xbf8b36b8, 24, 0)                          = 1\nfactorielle(5, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 5, ...)                                       = 9\n__isoc99_sscanf(0xbf8b5460, 0x8048796, 0xbf8b36b8, 120, 0)                         = 1\nfactorielle(6, 0xbf8b36b0)                                                         = 0\nfprintf(0xb7704500, \"%ld! = %lldn\", 6, ...)                                       = 9\n+++ exited (status 0) +++\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Nous pourrions aussi utiliser l&rsquo;option <code>-F<\/code> de <code>ltrace<\/code> pour pr\u00e9ciser les fichiers <code>ltrace.conf<\/code> \u00e0 utiliser.<\/p>\n<p style=\"text-align: justify;\">Cette fois-ci le r\u00e9sultat est parfait, nous voyons bien les appels de notre fonction, avec la valeur \u00e0 calculer, l&rsquo;adresse du r\u00e9sultat \u00e0 remplir et le statut de retour, <code>0<\/code> signifiant \u00ab\u00a0tout va bien\u00a0\u00bb.<\/p>\n<p style=\"text-align: justify;\">L&rsquo;utilisation de <code>ltrace<\/code>, et de sa commande cousine <code>strace<\/code> pour les appels-syst\u00e8me, est tr\u00e8s utile pour la mise au point d&rsquo;applications ou de biblioth\u00e8ques. Son aspect non-intrusif (pas d&rsquo;option de compilation particuli\u00e8re) et le fait que le code source ne soit pas n\u00e9cessaire le rend utilisable m\u00eame pour des programmes livr\u00e9s sous forme binaire seulement. Je me souviens de l&rsquo;avoir employ\u00e9 avec succ\u00e8s il y a quelques ann\u00e9es sur une application \u00e0 qui je devais fournir un fichier de configuration, mais pour lequel la documentation mentionnait un r\u00e9pertoire invalide. J&rsquo;ai donc lanc\u00e9 <code>ltrace<\/code> sur l&rsquo;application sans fournir de fichier de configuration. Bien entendu l&rsquo;application a refus\u00e9 de d\u00e9marrer, mais j&rsquo;ai pu chercher dans les traces (en filtrant avec <code>grep<\/code>) les lignes d&rsquo;ouverture de fichiers &#8211; avec <code>fopen()<\/code> &#8211; et voir les tentatives successives avant \u00e9chec (quelque chose comme <code>\/home\/cpb\/.APPLICATION\/<\/code>, <code>\/usr\/lib\/APPLICATION<\/code>, <code>\/etc\/APPLICATION<\/code>\u2026)<\/p>\n<h1 style=\"text-align: justify;\">D\u00e9bogage avec Gdb<\/h1>\n<p style=\"text-align: justify;\">Dans la plupart des cas, on consid\u00e8re, lorsqu&rsquo;on fait la mise au point d&rsquo;une application, les appels de biblioth\u00e8ques comme des invocations \u00e9l\u00e9mentaires, des fonctions sur le contenu desquelles on ne se pose pas de question. Pourtant, les biblioth\u00e8ques dynamiques peuvent elles aussi n\u00e9cessiter une mise au point et une analyse pas-\u00e0-pas de leur fonctionnement.<\/p>\n<p style=\"text-align: justify;\">Essayons d&rsquo;utiliser le d\u00e9bogueur <code>gdb<\/code> sur l&rsquo;ex\u00e9cutable que nous avons produit dans le pr\u00e9c\u00e9dent article.<\/p>\n<pre>[factorielle]$ <strong>gdb .\/test\/calcule-factorielle <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorielle\/test\/calcule-factorielle...(no debugging symbols found)...done.\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Le d\u00e9bogueur a bien trouv\u00e9 notre ex\u00e9cutable et l&rsquo;a charg\u00e9 en m\u00e9moire. Toutefois, il nous indique qu&rsquo;il ne dispose pas de la table de symboles n\u00e9cessaires au d\u00e9bogage. Essayons quand m\u00eame de poser un point d&rsquo;arr\u00eat en d\u00e9but de fonction <code>main<\/code>.<\/p>\n<pre>(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485b9\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Cela fonctionne. Lan\u00e7ons le programme avec une valeur en argument.<\/p>\n<pre>(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorielle\/test\/calcule-factorielle 5\nBreakpoint 1, 0x080485b9 in main ()\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Nous sommes arr\u00eat\u00e9s en debut de <code>main()<\/code>, essayons d&rsquo;avancer d&rsquo;une instruction.<\/p>\n<pre>(gdb) next\nSingle stepping until exit from function main,\nwhich has no line number information.\n5! = 120\n0xb7e62113 in __libc_start_main () from \/lib\/i386-linux-gnu\/libc.so.6\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Et oui, le d\u00e9bogueur n&rsquo;a pas de notion de ligne de code, il va d&rsquo;une seule traite jusqu&rsquo;\u00e0 la fin de <code>main()<\/code>. Nous ne pouvons que laisser le processus se terminer et quitter le d\u00e9bogueur.<\/p>\n<pre>(gdb) <strong>cont<\/strong>\nContinuing.\n[Inferior 1 (process 15847) exited normally]\nUndefined command: \"exit\".  Try \"help\".\n(gdb) <strong>quit<\/strong>\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Compilons notre ex\u00e9cutable avec l&rsquo;option <code>-g<\/code> pour y int\u00e9grer une table de correspondance entre les adresses m\u00e9moire et les lignes de code source. Puis r\u00e9it\u00e9rons l&rsquo;exp\u00e9rience.<\/p>\n<pre>[factorielle]$ <strong>gcc -I include\/ -L lib\/ -o test\/calcule-factorielle test\/calcule-factorielle.c -l fact -g<\/strong>\n[factorielle]$ <strong>gdb .\/test\/calcule-factorielle <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;\nReading symbols from \/home\/cpb\/factorielle\/test\/calcule-factorielle...done.\n(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485bf: file test\/calcule-factorielle.c, line 11.\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorielle\/test\/calcule-factorielle 5\n\nBreakpoint 1, main (argc=2, argv=0xbffff274) at test\/calcule-factorielle.c:11\n11\t\tif (argc &lt; 2) {\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Cette fois nous remarquons que <code>gdb<\/code> nous affiche correctement la ligne 11. Continuons \u00e0 avancer en pas-\u00e0-pas avec la commande <code>step<\/code>.<\/p>\n<pre>(gdb) <strong>step<\/strong>\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n16\t\t\tif (sscanf(argv[i], \"%ld\", &amp; n) == 1) {\n(gdb) <strong>step<\/strong>\n17\t\t\t\tif (factorielle(n, &amp; f) == 0)\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Malheureusement <code>gdb<\/code> ne dispose pas des sources de la biblioth\u00e8que, aussi ne nous permet-il pas de rentrer dans la fonction <code>factorielle()<\/code>, pas plus qu&rsquo;il ne le fait pour <code>sscanf()<\/code> ou <code>fprintf()<\/code>.<\/p>\n<pre>(gdb) <strong>step<\/strong>\n18\t\t\t\t\tfprintf(stdout, \"%ld! = %lldn\", n, f);\n(gdb) <strong>step<\/strong>\n5! = 120\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n22\t\treturn EXIT_SUCCESS;\n(gdb) <strong>step<\/strong>\n23\t}\n(gdb) <strong>step<\/strong>\n0xb7e62113 in __libc_start_main () from \/lib\/i386-linux-gnu\/libc.so.6\n(gdb) <strong>step<\/strong>\nSingle stepping until exit from function __libc_start_main,\nwhich has no line number information.\n[Inferior 1 (process 27455) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorielle]$<\/pre>\n<h2>D\u00e9bogage de la biblioth\u00e8que<\/h2>\n<p style=\"text-align: justify;\">Nous devons compiler notre biblioth\u00e8que avec l&rsquo;option <code>-g<\/code> ainsi.<\/p>\n<pre>[factorielle]$ <strong>gcc -I include\/ -o src\/fact.o -c src\/fact.c -g<\/strong>\n[factorielle]$ <strong>gcc -shared -I include\/ -Wl,-soname,libfact.so.2 -o lib\/libfact.so.2.0 src\/fact.o <\/strong>\n[factorielle]$ <strong>gcc -I include\/ -L lib\/ -o test\/calcule-factorielle test\/calcule-factorielle.c -l fact -g<\/strong><\/pre>\n<p style=\"text-align: justify;\">Puis lancer le d\u00e9bogage.<\/p>\n<pre>[factorielle]$ <strong>gdb .\/test\/calcule-factorielle <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorielle\/test\/calcule-factorielle...done.\n(gdb) <strong>break main<\/strong>\nBreakpoint 1 at 0x80485bf: file test\/calcule-factorielle.c, line 11.\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorielle\/test\/calcule-factorielle 5\n(gdb) <strong>break main<\/strong>\nBreakpoint 1, main (argc=2, argv=0xbffff274) at test\/calcule-factorielle.c:11\n11\t\tif (argc &lt; 2) {\n(gdb) <strong>step<\/strong>\n15\t\tfor (i = 1; i &lt; argc; i ++)\n(gdb) <strong>step<\/strong>\n16\t\t\tif (sscanf(argv[i], \"%ld\", &amp; n) == 1) {\n(gdb) <strong>step<\/strong>\n17\t\t\t\tif (factorielle(n, &amp; f) == 0)\n(gdb) <strong>step<\/strong>\nfactorielle (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\t\t* result = 1;\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Nous sommes bien dans notre routine <code>factorielle()<\/code>, continuons quelques instructions en pas-\u00e0-pas&#8230;<\/p>\n<pre>(gdb) <strong>step<\/strong>\n6\t\tif (n &lt; 0)\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>step<\/strong>\n10\t\t\tn = n - 1;\n(gdb) <strong>step<\/strong>\n11\t\t} while (n &gt; 1);\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>step<\/strong>\n10\t\t\tn = n - 1;\n(gdb)<\/pre>\n<p style=\"text-align: justify;\">Nous pouvons \u00e9galement examiner l&rsquo;\u00e9tat des variables. La pr\u00e9sentation du r\u00e9sultat par <code>gdb<\/code> est un peu surprenante de prime abord, car il pr\u00e9fixe les expressions d&rsquo;un <code>$<\/code> suivi d&rsquo;un num\u00e9ro d&rsquo;ordre de ses \u00e9valuations. Ceci permet d&rsquo;\u00e9crire facilement des frontaux graphiques (comme <code>ddd<\/code>, <code>xxgdb<\/code>, Eclipse, etc.) qui r\u00e9cup\u00e8rent les valeurs renvoy\u00e9es.<\/p>\n<pre>(gdb) <strong>print *result<\/strong>\n$1 = 20\n(gdb) <strong>print n<\/strong>\n$2 = 4\n(gdb) <strong>cont<\/strong>\nContinuing.\n5! = 120\n[Inferior 1 (process 30206) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorielle]$<\/pre>\n<h2>Emplacement des sources<\/h2>\n<p style=\"text-align: justify;\">L&#8217;emplacement des sources de la biblioth\u00e8que est mentionn\u00e9 dans le fichier ex\u00e9cutable lors de la compilation avec l&rsquo;option <code>-g<\/code>. Toutefois elles peuvent \u00eatre d\u00e9plac\u00e9es ou la biblioth\u00e8que peut \u00eatre compil\u00e9e sur une autre machine que celle utilis\u00e9e pour le d\u00e9bogage. Il faut donc disposer d&rsquo;un moyen d&rsquo;indiquer \u00e0 <code>gdb<\/code> l&rsquo;endroit o\u00f9 se trouvent les fichiers source de la biblioth\u00e8que. Faisons un essai en d\u00e9pla\u00e7ant les sources de la biblioth\u00e8que dans un r\u00e9pertoire totalement ind\u00e9pendant.<\/p>\n<pre>[factorielle]$ <strong>mkdir -p ~\/tmp\/sources<\/strong>\n[factorielle]$ <strong>mv src\/* ~\/tmp\/sources\/<\/strong>\n[factorielle]$ <strong>gdb .\/test\/calcule-factorielle <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorielle\/test\/calcule-factorielle...done.\n(gdb) <strong>break factorielle<\/strong>\nBreakpoint 1 at 0x80484f0\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorielle\/test\/calcule-factorielle 5\n\nBreakpoint 1, factorielle (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\tsrc\/fact.c: Aucun fichier ou dossier de ce type.\n\tin src\/fact.c\n(gdb) <strong>quit<\/strong>\nA debugging session is active.\n\n\tInferior 1 [process 31536] will be killed.\n\nQuit anyway? (y or n) <strong>y<\/strong>\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">\u00c9videmment le d\u00e9bogage \u00e9choue. Utilisons \u00e0 pr\u00e9sent la commande <code>directory<\/code> de <code>gdb<\/code>.<\/p>\n<pre>[factorielle]$ <strong>gdb .\/test\/calcule-factorielle <\/strong>\nGNU gdb (Ubuntu\/Linaro 7.3-0ubuntu2) 7.3-2011.08\nCopyright (C) 2011 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later &lt;http:\/\/gnu.org\/licenses\/gpl.html&gt;\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\nThis GDB was configured as \"i686-linux-gnu\".\nFor bug reporting instructions, please see:\n&lt;http:\/\/bugs.launchpad.net\/gdb-linaro\/&gt;...\nReading symbols from \/home\/cpb\/factorielle\/test\/calcule-factorielle...done.\n(gdb)<strong> directory ~\/tmp\/sources\/<\/strong>\nSource directories searched: \/home\/cpb\/tmp\/sources:$cdir:$cwd\n(gdb) <strong>break factorielle<\/strong>\nBreakpoint 1 at 0x80484f0\n(gdb) <strong>run 5<\/strong>\nStarting program: \/home\/cpb\/factorielle\/test\/calcule-factorielle 5\n\nBreakpoint 1, factorielle (n=5, result=0xbffff1c0) at src\/fact.c:5\n5\t\t* result = 1;\n(gdb) <strong>step<\/strong>\n6\t\tif (n &lt; 0)\n(gdb) <strong>step<\/strong>\n9\t\t\t(*result) = (*result) * n;\n(gdb) <strong>cont<\/strong>\nContinuing.\n5! = 120\n[Inferior 1 (process 31845) exited normally]\n(gdb) <strong>quit<\/strong>\n[factorielle]$<\/pre>\n<p style=\"text-align: justify;\">Cela fonctionne parfaitement.<\/p>\n<h1>Conclusion<\/h1>\n<p style=\"text-align: justify;\">Nous avons examin\u00e9 deux \u00e9tapes importantes pour la mise au point d&rsquo;une biblioth\u00e8que&nbsp;: le suivi des appels et le d\u00e9bogage pas-\u00e0-pas. Nous examinerons les tests en couverture dans le prochain article.<\/p>","protected":false},"excerpt":{"rendered":"<p>(English translation) Nous avons examin&eacute; dans l&rsquo;article pr&eacute;c&eacute;dent comment compiler une biblioth&egrave;que dynamique et g&eacute;rer correctement ses num&eacute;ros majeurs et mineurs de version afin d&rsquo;en faciliter la maintenance, tant pour le d&eacute;veloppeur (de la biblioth&egrave;que mais aussi pour celui des applications qui l&rsquo;utilisent) que pour l&rsquo;administrateur du syst&egrave;me sur lequel elle est install&eacute;e. Nous allons [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1540","post","type-post","status-publish","format-standard","hentry","category-linux-2"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=1540"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/1540\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=1540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=1540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=1540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}