<!--
        The FreeBSD Documentation Project
        The FreeBSD French Documentation Project

        $FreeBSD$
        Original revision: 1.13
--> 

<chapter id="kerneldebug">
  <title>D&eacute;boguer le noyau</title>
  
  <para><emphasis>Contribution de &a.paul; et &a.joerg;</emphasis></para>
  &trans.a.haby;
  
  <sect1>
    <title>D&eacute;boguer une trace de 
      plantage&nbsp;-&nbsp;<foreignphrase>crash 
      dump</foreignphrase>&nbsp;-&nbsp;avec <command>kgdb</command></title>
    
    <para>Voici quelques instructions pour d&eacute;boguer le noyau en cas de
      plantage. Elles supposent que vous avez suffisamment d'espace de
      pagination pour enregistrer la trace du plantage. Si vous avez plusieurs
      partitions de pagination et que la premi&egrave;re est trop petite pour
      archiver cette trace, vous pouvez configurer votre noyau pour utiliser
      un autre fichier sp&eacute;cial de p&eacute;riph&eacute;rique pour stocker
      cette trace (&agrave; la ligne <literal>config kernel</literal>) ou vous
      pouvez indiquer un autre fichier sp&eacute;cial de 
      p&eacute;riph&eacute;rique avec la commande &man.dumpon.8;. La meilleure
      m&eacute;thode pour utiliser &man.dumpon.8; consiste &agrave; positionner
      la variable <literal>dumpdev</literal> dans 
      <filename>/etc/rc.conf</filename>. Vous utiliserez typiquement une des
      partitions de pagination d&eacute;finies dans 
      <filename>/etc/fstab</filename>. L'enregistrement de la trace sur d'autres
      fichiers sp&eacute;ciaux de p&eacute;riph&eacute;riques que les partitions
      de pagination, des bandes par exemple, n'est actuellement pas 
      support&eacute;. Configurez votre noyau avec <command>config -g</command>.
      Reportez-vous au chapitre <link linkend="kernelconfig">Configuration du 
      noyau de FreeBSD</link> pour avoir plus de d&eacute;tails sur la 
      mani&egrave;re de proc&eacute;der.</para>

    <para>Utilisez la commande &man.dumpon.8; pour dire au noyau o&ugrave;
      enregistrer la trace (notez que cela doit &ecirc;tre fait apr&egrave;s
      avoir configur&eacute; la partition en question comme partition de 
      pagination avec &man.swapon.8;). C'est normalement fait via
      <filename>/etc/rc.conf</filename> et <filename>/etc/rc</filename>. Vous
      pouvez aussi d&eacute;finir le fichier sp&eacute;cial de trace avec la
      clause <literal>dump</literal> de la ligne <literal>config</literal> du
      fichier de configuration du noyau. C'est d&eacute;pr&eacute;ci&eacute;
      et ne devrait &ecirc;tre utilis&eacute; que si vous voulez la trace d'un
      plantage du noyau lors du d&eacute;marrage du syst&egrave;me.</para>
    
    <note>
      <para>Dans ce qui suit, le terme <command>kgdb</command> se rapporte
	&agrave; <command>gdb</command> ex&eacute;cut&eacute; en &ldquo;mode 
        d&eacute;boguage du noyau&rdquo;. Cela se fait soit en lan&ccedil;ant
	<command>gdb</command> avec l'option <option>-k</option>, soit en
        le g&eacute;n&eacute;rant et en le lan&ccedil;ant sous le nom
	<command>kgdb</command>. Ce n'est cependant pas fait par d&eacute;faut,
        et c'est une fa&ccedil;on de faire obsol&egrave;te, parce que les gens
        du projet GNU n'aiment pas que leurs outils se comportent 
        diff&eacute;remment quand ils sont appel&eacute;s d'un autre nom. Cette
        fonctionnalit&eacute; pourrait dispara&icirc;tre des versions 
        futures.</para>
    </note>
    
    <para>Une fois que le noyau a &eacute;t&eacute; compil&eacute;, faites-en 
      une copie, disons <filename>kernel.debug</filename>, et ex&eacute;cutez
      <command>strip -d</command> sur l'original. Installez l'original comme
      d'habitude. Vous pouvez aussi installer le noyau non expurg&eacute;, mais
      le temps de recherche dans la table des symboles augmentera de 
      fa&ccedil;on dramatique pour certains programmes, et comme le noyau
      est int&eacute;gralement charg&eacute; en m&eacute;moire au 
      d&eacute;marrage et y reste ensuite, vous gaspillerez plusieurs Mo de
      m&eacute;moire physique.</para>
	
    <para>Si vous testez un nouveau noyau, par exemple en donnant le nom de ce
      noyau au d&eacute;marrage, mais avez besoin de d&eacute;marrez avec un
      autre noyau pour avoir de nouveau un syst&egrave;me en &eacute;tat de
      marche, d&eacute;marrez uniquement en mode mono-utilisateur avec
      l'indicateur <option>-s</option> &agrave; l'invite de d&eacute;marrage et
      effectuez ensuite les &eacute;tapes suivantes&nbsp;:</para>

    <screen>&prompt.root; <userinput>fsck -p</userinput>
&prompt.root; <userinput>mount -a -t ufs</userinput>       # de fa&ccedil;on &agrave; ce qu'il soit possible d'&eacute;crire
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# sur le syst&egrave;me de fichiers pour /var/crash
&prompt.root; <userinput>savecore -N /kernel.panicked /var/crash</userinput>
&prompt.root; <userinput>exit</userinput>                  # ... en mode multi-utilisateur</screen>
	  
    <para>Cela dit &agrave; &man.savecore.8; d'utiliser un autre noyau pour y
      chercher les noms des symboles. Il utiliserait sans cela le noyau en cours
      d'ex&eacute;cution et cela ne m&eacute;nerait probablement &agrave; rien,
      puisque les symboles de la trace de plantage et ceux du noyau ne sont pas
      les m&ecirc;mes.</para>
    
    <para>Maintenant, apr&egrave;s un plantage, allez dans
      <filename>/sys/compile/QUELQUE_CHOSE</filename> et lancez
      <command>kgdb</command>. Sous <command>kgdb</command>, tapez&nbsp;:</para>
	  
      <screen><userinput>symbol-file kernel.debug</userinput>
<userinput>exec-file /var/crash/kernel.0</userinput>
<userinput>core-file /var/crash/vmcore.0</userinput></screen>
	  
      <para>et voil&agrave;, vous pouvez maintenant d&eacute;boguer la trace de
        plantage en vous servant des sources du noyau comme vous le feriez pour
        n'importe quel autre programme.</para>

    <para>Voici la trace d'une session <command>kgdb</command> qui illustre la
      fa&ccedil;on de proc&eacute;der. Les lignes trop longues ont 
      &eacute;t&eacute; scind&eacute;es pour en faciliter la lecture, et les
      lignes sont num&eacute;rot&eacute;es pour pouvoir y faire 
      r&eacute;f&eacute;rence. Malgr&eacute; cela, c'est un exemple grandeur
      nature, correspondant &agrave; une trace prise lors du 
      d&eacute;veloppement du pilote <devicename>pcvt</devicename>.</para>
    
<screen> 1:Script started on Fri Dec 30 23:15:22 1994
 2:&prompt.root; <userinput>cd /sys/compile/URIAH</userinput>
 3:&prompt.root; <userinput>kgdb kernel /var/crash/vmcore.1</userinput> 
 4:Reading symbol data from /usr/src/sys/compile/URIAH/kernel
...done.
 5:IdlePTD 1f3000
 6:panic: because you said to!
 7:current pcb at 1e3f70
 8:Reading in symbols for ../../i386/i386/machdep.c...done.
 9:<prompt>(kgdb)</prompt> <userinput>where</userinput>
10:#0  boot (arghowto=256) (../../i386/i386/machdep.c line 767)
11:#1  0xf0115159 in panic ()
12:#2  0xf01955bd in diediedie () (../../i386/i386/machdep.c line 698)
13:#3  0xf010185e in db_fncall ()
14:#4  0xf0101586 in db_command (-266509132, -266509516, -267381073)
15:#5  0xf0101711 in db_command_loop ()
16:#6  0xf01040a0 in db_trap ()
17:#7  0xf0192976 in kdb_trap (12, 0, -272630436, -266743723)
18:#8  0xf019d2eb in trap_fatal (...)
19:#9  0xf019ce60 in trap_pfault (...)
20:#10 0xf019cb2f in trap (...)
21:#11 0xf01932a1 in exception:calltrap ()
22:#12 0xf0191503 in cnopen (...)
23:#13 0xf0132c34 in spec_open ()
24:#14 0xf012d014 in vn_open ()
25:#15 0xf012a183 in open ()
26:#16 0xf019d4eb in syscall (...)
27:<prompt>(kgdb)</prompt> <userinput>up 10</userinput>
28:Reading in symbols for ../../i386/i386/trap.c...done.
29:#10 0xf019cb2f in trap (frame={tf_es = -260440048, tf_ds = 16, tf_\
30:edi = 3072, tf_esi = -266445372, tf_ebp = -272630356, tf_isp = -27\
31:2630396, tf_ebx = -266427884, tf_edx = 12, tf_ecx = -266427884, tf\
32:_eax = 64772224, tf_trapno = 12, tf_err = -272695296, tf_eip = -26\
33:6672343, tf_cs = -266469368, tf_eflags = 66066, tf_esp = 3072, tf_\
34:ss = -266427884}) (../../i386/i386/trap.c line 283)
35:283                             (void) trap_pfault(&amp;frame, FALSE);
36:<prompt>(kgdb)</prompt> <userinput>frame frame-&gt;tf_ebp frame-&gt;tf_eip</userinput>
37:Reading in symbols for ../../i386/isa/pcvt/pcvt_drv.c...done.
38:#0  0xf01ae729 in pcopen (dev=3072, flag=3, mode=8192, p=(struct p\
39:roc *) 0xf07c0c00) (../../i386/isa/pcvt/pcvt_drv.c line 403)
40:403             return ((*linesw[tp-&gt;t_line].l_open)(dev, tp));
41:<prompt>(kgdb)</prompt> <userinput>list</userinput>
42:398        
43:399             tp-&gt;t_state |= TS_CARR_ON;
44:400             tp-&gt;t_cflag |= CLOCAL;  /* cannot be a modem (:-) */
45:401     
46:402     #if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
47:403             return ((*linesw[tp-&gt;t_line].l_open)(dev, tp));
48:404     #else
49:405             return ((*linesw[tp-&gt;t_line].l_open)(dev, tp, flag));
50:406     #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
51:407     }
52:<prompt>(kgdb)</prompt> <userinput>print tp</userinput>
53:Reading in symbols for ../../i386/i386/cons.c...done.
54:$1 = (struct tty *) 0x1bae
55:<prompt>(kgdb)</prompt> <userinput>print tp-&gt;t_line</userinput>
56:$2 = 1767990816
57:<prompt>(kgdb)</prompt> <userinput>up</userinput>
58:#1  0xf0191503 in cnopen (dev=0x00000000, flag=3, mode=8192, p=(st\
59:ruct proc *) 0xf07c0c00) (../../i386/i386/cons.c line 126)
60:       return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p));
61:<prompt>(kgdb)</prompt> <userinput>up</userinput>
62:#2  0xf0132c34 in spec_open ()
63:<prompt>(kgdb)</prompt> <userinput>up</userinput>
64:#3  0xf012d014 in vn_open ()
65:<prompt>(kgdb)</prompt> <userinput>up</userinput>
66:#4  0xf012a183 in open ()
67:<prompt>(kgdb)</prompt> <userinput>up</userinput>
68:#5  0xf019d4eb in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi =\
69: 2158592, tf_esi = 0, tf_ebp = -272638436, tf_isp = -272629788, tf\
70:_ebx = 7086, tf_edx = 1, tf_ecx = 0, tf_eax = 5, tf_trapno = 582, \
71:tf_err = 582, tf_eip = 75749, tf_cs = 31, tf_eflags = 582, tf_esp \
72:= -272638456, tf_ss = 39}) (../../i386/i386/trap.c line 673)
73:673             error = (*callp-&gt;sy_call)(p, args, rval);
74:<prompt>(kgdb)</prompt> <userinput>up</userinput>
75:Initial frame selected; you cannot go up.
76:<prompt>(kgdb)</prompt> <userinput>quit</userinput>
77:&prompt.root; <userinput>exit</userinput>
78:exit
79:
80:Script done on Fri Dec 30 23:18:04 1994</screen>
    <para>Commentaires sur les r&eacute;sultats ci-dessus&nbsp;:</para>
    
    <variablelist>
      <varlistentry>
	<term>ligne 6&nbsp;:</term>

	<listitem>
	  <para>C'est une trace obtenue depuis DDB (voir plus bas), d'o&ugrave; 
            le commentaire panique &ldquo;<foreignphrase>because you said 
            to!</foreignphrase>&nbsp;-&nbsp;parce que vous l'avez 
            demand&eacute;&rdquo;&nbsp;-&nbsp;et une assez longue trace de la 
            pile d'ex&eacute;cution; la raison initiale du passage sous DDB est
            n&eacute;anmoins la d&eacute;tection d'un d&eacute;faut de 
            page.</para>
	</listitem>
      </varlistentry>
      
      <varlistentry>
	<term>ligne 20&nbsp;:</term>
	
	<listitem>
	  <para>C'est la position de l'appel &agrave; la fonction 
            <function>trap()</function> dans la pile.</para>
	</listitem>
      </varlistentry>
      
      <varlistentry>
	<term>ligne 36&nbsp;:</term>
	
	<listitem>
	  <para>Impose l'utilisation d'un nouveau contexte de 
            pile&nbsp;-&nbsp;<foreignphrase>stack frame</foreignphrase>; ce 
            n'est dor&eacute;navant plus n&eacute;cessaire. Les contextes de 
            pile sont maintenant cens&eacute;s pointer sur les bonnes adresses,
            m&ecirc;me en cas de d&eacute;branchement. (Je n'ai pas de trace
            r&eacute;cente de plantage sous la main; mon noyau n'a pas     
            paniqu&eacute; depuis un certain temps.) Au vu de la ligne 403 du 
            code source, il y a de fortes chances pour que soit le pointeur de
	    &ldquo;tp&rdquo; soit erronn&eacute; soit il y ait 
            d&eacute;bordement dans le tableau.</para>
	</listitem>
      </varlistentry>
      
      <varlistentry>
	<term>ligne 52&nbsp;:</term>
	
	<listitem>
	  <para>Le pointeur semble suspect, mais il se trouve que l'adresse est
            valide.</para>
	</listitem>
      </varlistentry>
      
      <varlistentry>
	<term>ligne 56&nbsp;:</term>
	
	<listitem>
	  <para>Il pointe cependant sur n'importe quoi, nous avons donc 
            trouv&eacute; notre erreur! (Pour ceux qui ne sont pas 
            familiaris&eacute;s avec ce code particulier&nbsp;: 
            <literal>tp-&gt;t_line</literal> se rapporte &agrave; la gestion de
            la liaison&nbsp;-&nbsp;<foreignphrase>line 
            discipline</foreignphrase>&nbsp;-&nbsp;du p&eacute;riph&eacute;rique
            console, qui doit &ecirc;tre un entier assez petit.)</para>
	</listitem>
      </varlistentry>
    </variablelist>
  </sect1>
  
  <sect1>
    <title>D&eacute;boguer une trace de plantage avec DDD</title>
    
    <para>Il est aussi possible d'examiner une trace de plantage avec un
      d&eacute;bogueur graphique comme <command>ddd</command>. Ajoutez l'option
      <option>-k</option> &agrave; la ligne de commande de 
      <command>ddd</command> que vous utiliseriez normalement. Par 
      exemple&nbsp;:</para>

    <screen>&prompt.root; <userinput>ddd -k /var/crash/kernel.0 /var/crash/vmcore.0</userinput></screen>
    
    <para>Vous devriez maintenant pouvoir examiner la trace de plantage avec
      l'interface graphique de <command>ddd</command>.</para>
  </sect1>
  
  <sect1>
    <title>Analyser la trace apr&egrave;s plantage</title>
    
    <para>Que faire si le noyau plante alors que vous ne l'aviez pas 
      pr&eacute;vu et donc que vous ne l'avez pas compil&eacute; avec
      <command>config -g</command>&nbsp;? Tout n'est pas perdu. Ne paniquez
      pas&nbsp;!</para>
	
    <para>Il faut bien s&ucirc;r que vous autorisiez l'archivage des traces de
      plantage. Voyez plus haut quelles options vous devez utiliser pour
      cela.</para>
	
    <para>Allez dans le r&eacute;pertoire de compilation de votre noyau et
      &eacute;ditez la ligne contenant <literal>COPTFLAGS?=-O</literal>. 
      Ajoutez-y l'option <option>-g</option> (mais ne changez 
      <emphasis>rien</emphasis> au niveau d'optimisation. Si vous avez 
      d&eacute;j&agrave; une vague id&eacute;e de l&agrave; o&ugrave; se situe 
      le code fautif (e.g., le pilote <devicename>pcvt</devicename> dans
      l'exemple pr&eacute;c&eacute;dent), supprimez tous les fichiers objets
      correspondant &agrave; ce code. Recompilez le noyau. Du fait de la
      modification de la date du <filename>Makefile</filename>, d'autres
      objets seront reconstruits, par exemple, <filename>trap.o</filename>. Avec
      un peu de chance, l'option suppl&eacute;mentaire <option>-g</option> ne
      changera rien au code g&eacute;n&eacute;r&eacute;, vous aurez donc un 
      nouveau noyau dont le code est similaire &agrave; celui qui a 
      plant&eacute; &agrave; l'exception de quelques symboles de 
      d&eacute;bogage. V&eacute;rifiez au moins les tailles des deux noyaux avec
      la commande &man.size.1;. Si elles ne correspondent pas, vous devrez
      probablement en rester l&agrave;.</para>
	
    <para>Examinez maintenant la trace comme d&eacute;crit plus haut. Il y aura
      probablement par endroit des symboles de d&eacute;bogage incomplets, comme
      on peut le voir dans la trace de la pile de l'exemple plus haut, o&ugrave;
      certaines fonctions sont list&eacute;es sans num&eacute;ro de ligne et
      liste d'arguments. S'il vous faut plus d'informations, supprimez les
      fichiers objets et reprenez la session <command>kgdb</command>
      jusqu'&agrave; ce que vous en sachiez assez.</para>
	
    <para>Il n'y a aucune garantie que tout cela marche, mais cela fera 
      l'affaire dans la plupart des cas.</para>
  </sect1>
  
  <sect1>
    <title>D&eacute;boguer en ligne le noyau avec DDB</title>
    
    <para>Tandis que <command>kgdb</command> comme d&eacute;bogueur hors-ligne
      procure une interface utilisateur de tr&egrave;s haut niveau, il y a
      certaines choses qu'il ne peut pas faire. Les principales sont la mise en
      place de points d'arr&ecirc;t et l'ex&eacute;cution pas -&agrave;-pas du
      code du noyau.</para>
	
    <para>Si vous devez faire du d&eacute;bogage de bas niveau de votre noyau,
      il y a un d&eacute;bogueur de bas niveau appel&eacute; DDB. Il permet la
      mise en place des points d'arr&ecirc;t, l'ex&eacute;cution instruction
      par instruction des fonctions du noyau, l'examen et la modification
      de variables du noyau, etc. Il ne peut cependant pas acc&eacute;der aux
      fichiers source du noyau et n'a acc&egrave;s qu'aux symboles globaux et
      statiques et non &agrave; la totalit&eacute; des informations comme
      <command>kgdb</command>.</para>
	
    <para>Pour configurer votre noyau pour y inclure DDB, ajoutez la ligne
      d'option&nbsp;:</para>
      
      <programlisting>
options DDB</programlisting>

    <para>&agrave; votre fichier de configuration et recompilez-le. 
      (Reportez-vous au chapitre <link linkend="kernelconfig">Configurer le 
      noyau de FreeBSD </link> pour plus de d&eacute;tails sur la configuration
      du noyau de FreeBSD.)</para>

    <note>
      <para>Si vous avez une ancienne version des blocs de d&eacute;marrage, les
        symboles du d&eacute;bogueur peuvent ne pas &ecirc;tre charg&eacute;s du
        tout. Mettez &agrave; jour les blocs de d&eacute;marrage; les versions
        r&eacute;centes chargent automagiquement les symboles de DDB.</para>
    </note>
    
    <para>Une fois que votre noyau incluant DDB s'ex&eacute;cute, il y a 
      plusieurs fa&ccedil;ons de passer sous DDB. La premi&egrave;re et la plus
      imm&eacute;diate est d'utiliser l'option <option>-d</option> d&egrave;s le
      d&eacute;marrage; Le noyau d&eacute;marrera en mode d&eacute;bogage et 
      passera sous DDB avant m&ecirc;me de tester la pr&eacute;sence des 
      p&eacute;riph&eacute;riques. Vous pouvez donc m&ecirc;me d&eacute;boguer 
      les fonctions de test et d'attachement des 
      p&eacute;riph&eacute;riques.</para>
	
    <para>Le seconde est d'utiliser une combinaison de touches du clavier,
      habituellement 
      <keycombo><keycap>Ctrl</keycap><keycap>Alt</keycap><keycap>>Esc</keycap></keycombo>.  
      Avec <devicename>syscons</devicename>, cette combinaison peut &ecirc;tre
      red&eacute;finie; certaines red&eacute;finitions distribu&eacute;es du 
      clavier le font, faites-y donc attention. Il existe une option pour les
      consoles s&eacute;rie qui permet d'utiliser un <keysym>Break</keysym> sur
      la ligne console pour passer sous DDB
      (<literal>options BREAK_TO_DEBUGGER</literal> dans le fichier de
      configuration du noyau). Ce n'est pas l'option par d&eacute;faut, parce
      qu'il y a de nombreux adaptateurs s&eacute;rie qui g&eacute;n&egrave;rent
      gratuitement un <keysym>Break</keysym>, par exemple, lorsque l'on
      d&eacute;branche le c&acirc;ble.</para>
	
    <para>Troisi&egrave;mement, le noyau passe sous DDB lorsqu'une condition
      panique intervient, s'il est configur&eacute; pour l'utiliser. En
      cons&eacute;quence, il vaut mieux ne pas configurer le noyau pour qu'il
      inclue DDB, si la machine n'est pas sous surveillance.</para>
	
    <para>Les commandes de DDB ressemblent assez &agrave; celles de
      <command>gdb</command>. La premi&egrave;re chose que vous devrez 
      probablement faire sera de placer un point d'arr&ecirc;t&nbsp;:</para>
    
    <screen><userinput>b nom-de-fonction</userinput>
<userinput>b adresse</userinput></screen>
	  
    <para>Par d&eacute;faut, les nombres sont normalement donn&eacute;s en
      hexad&eacute;cimal, mais, pour les distinguer des noms de symboles, les
      nombres hexad&eacute;cimaux qui commencent par les lettres 
      <literal>a-f</literal> doivent &ecirc;tre pr&eacute;c&eacute;d&eacute;s de
      <literal>0x</literal> (c'est facultatif pour les autres nombres). On peut
      utiliser des expressions simples, par exemple&nbsp;:
      <literal>nom-de-fonction + 0x103</literal>.</para>
	
    <para>Pour reprendre l'ex&eacute;cution interrompue du noyau, tapez
      simplement&nbsp;:</para>
    
    <screen><userinput>c</userinput></screen>
    
    <para>Pour avoir le trace de la pile d'ex&eacute;cution, tapez&nbsp;:</para>
    
    <screen><userinput>trace</userinput></screen>
    
    <note>
      <para>Remarquez que quand vous passez sous DDB avec une combinaison de 
        touches, le noyau traite en fait une interruption, le contenu de la pile
        d'ex&eacute;cution ne vous sera alors peut-&ecirc;tre pas tr&egrave;s 
        utile.</para>
    </note>
    
    <para>Si vous voulez supprimer un point d'arr&ecirc;t, servez-vous 
      de&nbsp;:</para>
    
    <screen><userinput>del</userinput>
<userinput>del expression-d&eacute;finissant-l'adresse</userinput></screen>
    
    <para>Le premier exemple sert imm&eacute;diatement apr&egrave;s &ecirc;tre
      arriv&eacute; &agrave; un point d'arr&ecirc;t et supprime ce point
      d'arr&ecirc;t. Le second exemple permet de supprimer n'importe quel point
      d'arr&ecirc;t, mais il faut donner son adresse exacte; on peut l'obtenir
      avec&nbsp;:</para>
    
    <screen><userinput>show b</userinput></screen>
    
    <para>Pour ex&eacute;cuter pas-&agrave;-pas le noyau, essayez&nbsp;:</para>
    
    <screen><userinput>s</userinput></screen>
    
    <para>Vous ex&eacute;cuterez ainsi pas-&agrave;-pas les fonctions, mais vous
      pouvez aussi faire en sorte que DDB aille jusqu'&agrave; l'instruction de
      retour d'une fonction avec&nbsp;:</para>
    
    <screen><userinput>n</userinput></screen>

    <note>
      <para>Ce n'est pas la m&ecirc;me chose que la commande
        <command>next</command> de <command>gdb</command>, mais c'est 
        l'&eacute;quivalent de la commande <command>finish</command>.</para>
    </note>
    
    <para>Pour consulter le contenu de la m&eacute;moire, employez (par 
      exemple)&nbsp;:</para>
      	  
      <screen><userinput>x/wx 0xf0133fe0,40</userinput>
<userinput>x/hd db_symtab_space</userinput>
<userinput>x/bc termbuf,10</userinput>
<userinput>x/s stringbuf</userinput></screen>
	  
    <para>pour acc&eacute;der &agrave; des mots/demi-mots/octets, et pour 
      afficher des cha&icirc;nes de valeurs
      hexad&eacute;cimales/d&eacute;cimales/caract&egrave;res. La valeur
      apr&egrave;s la virgule est le nombre d'&eacute;l&eacute;ments. Pour
      afficher les <literal>0x10</literal> &eacute;l&eacute;ments suivants,
      tapez simplement&nbsp;:</para>
	  
    <screen><userinput>x ,10</userinput></screen>
    
    <para>De m&ecirc;me, utilisez&nbsp;:</para>

      <screen><userinput>x/ia foofunc,10</userinput></screen>
	  
    <para>pour d&eacute;sassembler les <literal>0x10</literal> premi&egrave;res
      instructions de <function>foofunc</function>, et les afficher avec leur
      d&eacute;placement depuis le d&eacute;but de
      <function>foofunc</function>.</para>

    <para>Pour modifer le contenu de la m&eacute;moire, utilisez la commande
      d'&eacute;criture&nbsp;:</para>
    	  
    <screen><userinput>w/b termbuf 0xa 0xb 0</userinput>
<userinput>w/w 0xf0010030 0 0</userinput></screen>
	  
    <para>Le param&egrave;tre de la commande
      (<literal>b</literal>/<literal>h</literal>/<literal>w</literal>)
      indique la taille de la valeur &agrave; &eacute;crire, la premi&egrave;re
      expression qui suit est l'adresse o&ugrave; &eacute;crire et la suite est
      interpr&eacute;t&eacute;e comme donnant les valeurs &agrave; &eacute;crire
      en s&eacute;quence en m&eacute;moire.</para>
	
    <para>Si vous avez besoin de conna&icirc;tre le contenu des registres,
      servez-vous de&nbsp;:</para>

    <screen><userinput>show reg</userinput></screen>
	
    <para>Vous pouvez aussi afficher la valeur d'un seul registre avec, par
      exemple&nbsp;:</para>

      <screen><userinput>p $eax</userinput></screen>

    <para>et la modifier avec&nbsp;:</para>

    <screen><userinput>set $eax nouvelle-valeur</userinput></screen>
	  
    <para>Si vous voulez appeler une fonction du noyau depuis DDB, dites 
      simplement&nbsp;:</para>

    <screen><userinput>call func(arg1, arg2, ...)</userinput></screen>
    
    <para>La valeur de retour sera affich&eacute;e.</para>
    
    <para>Pour avoir un r&eacute;sum&eacute; du style &man.ps.1; des processus
      lanc&eacute;s, utilisez&nbsp;:</para>
    	  
    <screen><userinput>ps</userinput></screen>
    
    <para>Vous avez maintenant examin&eacute; la raison de l'&eacute;chec de
      votre noyau, et voulez red&eacute;marrer le syst&egrave;me. Rappelez-vous 
      que, selon la gravit&eacute; des dysfonctionnements 
      pr&eacute;c&eacute;dents, toutes les parties du noyau ne fonctionneront
      peut-&ecirc;tre pas comme pr&eacute;vu. Red&eacute;marrez votre 
      syst&egrave;me, avec l'un des moyens suivants&nbsp;:</para>

    <screen><userinput>call diediedie()</userinput></screen>
	  
    <para>Votre noyau enregistrera une trace de plantage et red&eacute;marrera,
      vous pourrez donc analyser &agrave; plus haut niveau la trace avec
      <command>kgdb</command>. Cette commande doit habituellement &ecirc;tre
      suivie d'une instruction <command>continue</command>. Il y a maintenant
      un alias pour cela&nbsp;: <command>panic</command>.</para>
    
    <screen><userinput>call boot(0)</userinput></screen>
    
    <para>C'est une bonne m&eacute;thode pour arr&ecirc;ter proprement le
      syst&egrave;me, ex&eacute;cuter <function>sync()</function> sur tous les
      disques et ensuite red&eacute;marrer. Tant que le disque et les interfaces
      du syst&egrave;me de fichier du noyau ne sont pas endommag&eacute;s, ce
      peut &ecirc;tre une bonne fa&ccedil;on d'arr&ecirc;ter presque proprement
      le syst&egrave;me.</para> 
    
    <screen><userinput>call cpu_reset()</userinput></screen>
    
    <para>est la m&eacute;thode ultime pour se sortir du d&eacute;sastre et 
      c'est &agrave; peu pr&egrave;s la m&ecirc;me chose que d'appuyer sur le
      Bouton Rouge.</para>
	
    <para>Si vous avez besoin d'un bref r&eacute;sum&eacute; des commandes, 
      tapez simplemement&nbsp;:</para>
    
    <screen><userinput>help</userinput></screen>
    
    <para>Il est n&eacute;anmoins chaudement recommand&eacute; d'avoir sous la
      main un exemplaire des pages de manuel de &man.ddb.4; lors d'une session
      de d&eacute;bogage. Rappelez-vous qu'il peut &ecirc;tre difficile de lire
      le manuel en ligne tandis que l'on ex&eacute;cute pas-&agrave;-pas le
      noyau.</para>
  </sect1>
  
  <sect1>
    <title>D&eacute;boguer en ligne le noyau en utilisant GDB &agrave; 
      distance</title>
    
    <para>Cette fonctionnalit&eacute; est support&eacute;e depuis FreeBSD 2.2,
      et est de fait tr&egrave;s &eacute;l&eacute;gante.</para>
    
    <para>GDB supporte d&eacute;j&agrave; depuis longtemps le 
      <emphasis>d&eacute;bogage &agrave; distance</emphasis>. Cela se fait avec
      un protocole tr&egrave;s simple sur une ligne s&eacute;rie. A l'inverse 
      des autres m&eacute;thode d&eacute;crite plus haut, il vous faudra pour 
      cela deux machines. L'une fournit l'environnement de d&eacute;bogage, y 
      compris la totalit&eacute; des sources, et un exemplaire du binaire du 
      noyau incluant tous les symboles, et l'autre est la machine cible qui 
      ex&eacute;cute un exemplaire identique du noyau (mais sans les 
      informations de d&eacute;bogage).</para>
	
    <para>Vous devrez configurer le noyau en question avec <command>config
      -g</command>, inclure <option>DDB</option> &agrave; sa configuration, et
      le compiler comme d'habitude. Cela donne un binaire assez imposant, du
      fait des informations de d&eacute;bogage. Copiez ce noyau sur la machine
      cible, supprimez les informations de d&eacute;bogage avec <command>strip
      -x</command>, et d&eacute;marrez avec l'option <option>-d</option>. 
      Reliez la premi&egrave;re ligne s&eacute;rie de la machine cible &agrave;
      n'importe quelle ligne s&eacute;rie de la machine de d&eacute;bogage. 
      Allez maintenant dans le r&eacute;pertoire de compilation du noyau de la 
      machine de d&eacute;bogage, et lancez <command>gdb</command>&nbsp;:</para>

    <screen>&prompt.user; <userinput>gdb -k kernel</userinput>
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.16 (i386-unknown-freebsd),
Copyright 1996 Free Software Foundation, Inc...
<prompt>(kgdb)</prompt> </screen>
	  
    <para>Initialisez la session de d&eacute;bogage &agrave; distance (en 
      supposant que l'on utilise le premier port s&eacute;rie) 
      avec&nbsp;:</para>

    <screen><prompt>(kgdb)</prompt> <userinput>target remote /dev/cuaa0</userinput></screen>
	  
    <para>Puis, sur la machine cible (celle qui est pass&eacute;e sous DDB avant
      m&ecirc;me de tester la pr&eacute;sence des p&eacute;riph&eacute;riques),
      tapez&nbsp;:</para>
    
    <screen>Debugger("Boot flags requested debugger")
Stopped at Debugger+0x35: movb	$0, edata+0x51bc
<prompt>db&gt;</prompt> <userinput>gdb</userinput></screen>
	  
    <para>DDB r&eacute;pondra par&nbsp;:</para>
		  
    <screen>Next trap will enter GDB remote protocol mode</screen>
    
    <para>Chaque que vous taperez <command>gdb</command>, vous passerez de GDB
      &agrave; distance &agrave; DDB en local et inversement. Pour basculer
      imm&eacute;diatement, tapez simplement <command>s</command> 
      (<foreignphrase>step</foreignphrase>). Votre GDB h&ocirc;te aura 
      maintenant le contr&ocirc;le du noyau cible&nbsp;:</para>
		  
    <screen>Remote debugging using /dev/cuaa0
Debugger (msg=0xf01b0383 "Boot flags requested debugger")
    at ../../i386/i386/db_interface.c:257
<prompt>(kgdb)</prompt></screen>
		
    <para>Vous pouvez faire sous cette session &agrave; peu pr&egrave;s les
      m&ecirc;mes choses qu'avec n'importe quelle autre session GDB, y compris
      acc&eacute;der int&eacute;gralement au source, l'ex&eacute;cuter en  mode
      <foreignphrase>gud</foreignphrase> dans une fen&ecirc;tre Emacs (ce qui
      provoque l'affichage automatique du code source dans une autre
      fen&ecirc;tre Emacs), etc.</para>
    
    <para>GDB peut aussi &ecirc;tre utilis&eacute; &agrave; distance pour 
      d&eacute;boguer des modules du noyau &agrave; chargement 
      dynamique&nbsp;-&nbsp;<foreignphrase>LKM</foreignphrase>. Compilez d'abord
      le module avec les symboles de d&eacute;bogage&nbsp;:</para>

    <screen>&prompt.root; <userinput>cd /usr/src/lkm/linux</userinput>
&prompt.root; <userinput>make clean; make COPTS=-g</userinput></screen>
	  
    <para>Installez ensuite cette version du module sur la machine cible, 
      chargez-le et utilisez <command>modstat</command> pour trouver o&ugrave;
      il a &eacute;t&eacute; charg&eacute;&nbsp:</para>

    <screen>&prompt.root; <userinput>linux</userinput>
&prompt.root; <userinput>modstat</userinput>
Type     Id Off Loadaddr Size Info     Rev Module Name
EXEC      0   4 f5109000 001c f510f010   1 linux_mod</screen>
	  
    <para>Prenez l'adresse de chargement et ajoutez-y <literal>0x20</literal>
      (probablement pour prendre en compte l'en-t&ecirc;te a.out). C'est
      l'adresse o&ugrave; le code du module a &eacute;t&eacute; relog&eacute;.
      Utilisez la commande <command>add-symbol-file</command> de GDB pour
      informer le d&eacute;bogueur de l'existence du module&nbsp;:</para>

    <screen><prompt>(kgdb)</prompt> <userinput>add-symbol-file /usr/src/lkm/linux/linux_mod.o 0xf5109020</userinput>
add symbol table from file "/usr/src/lkm/linux/linux_mod.o" at
text_addr = 0xf5109020? (y or n) <userinput>y</userinput>
<prompt>(kgdb)</prompt></screen>
	  
    <para>Vous avez maintenant acc&egrave;s &agrave; tous les symboles du 
      module.</para>
  </sect1>
      
  <sect1>
    <title>D&eacute;boguer un pilote de console</title>
	
    <para>Comme vous avez besoin d'un pilote de console pour faire tourner DDB,
      les choses sont plus compliqu&eacute;es si c'est le pilote de console
      lui-m&ecirc;me qui a des probl&egrave;mes. Vous pouvez penser &agrave;
      utiliser une console s&eacute;rie (soit avec des blocs de d&eacute;marrage
      modifi&eacute;s, soit en utilisant l'option <option>-h</option> &agrave;
      l'invite <prompt>Boot:</prompt>) et connecter un terminal standard au
      premier port s&eacute;rie. DDB fonctionne avec n'importe quel pilote de
      console configur&eacute;, donc bien s&ucirc;r aussi avec une console 
      s&eacute;rie.</para>
  </sect1>
</chapter>

<!-- 
     Local Variables:
     mode: sgml
     sgml-declaration: "../chapter.decl"
     sgml-indent-data: t
     sgml-omittag: nil
     sgml-always-quote-attributes: t
     sgml-parent-document: ("../handbook.sgml" "part" "chapter")
     End:
-->

