Obligement - L'Amiga au maximum

Vendredi 23 mai 2025 - 07:09  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


En pratique : Utilisation de GDB 6.3 sous AmigaOS 4.1
(Article écrit par Mathias Parnaudeau et extrait de GuruMed.net - novembre 2009)


GNU Debugger, également appelé GDB, est le débogueur standard du projet GNU. Il a été porté sur de nombreux systèmes type Unix, dont AmigaOS 4.1 et fonctionne pour plusieurs langages de programmation, comme le C, C++, Fortran, Ada, Objective-C, et le Go. Il fut écrit par Richard Stallman en 1988.

1. GDB - pourquoi vivre sans ?

La méthode de débogage de base est le printf(). Alors, pourquoi ne pas l'utiliser et se casser la tête avec un débogueur ?
  • On a souvent besoin de mettre et retirer un tas de printf() un peu partout et c'est casse bonbon, ça retire l'attention de là où on devrait la mettre.
  • printf() ne peut pas changer le contenu d'une variable.
  • printf() ne peut pas arrêter le programme temporairement.
  • printf() ne peut pas nous rappeler le type d'une variable.
  • printf() ne peut pas sauter à une ligne de code arbitraire.
  • printf() ne peut pas s'attacher à un processus en cours d'exécution.
De là à dire que les masochistes raffinés utilisent printf() il n'y a qu'un pas que je vous laisse le loisir de franchir.

2. GDB - comment en profiter ?

GDB a besoin d'informations pour vous indiquer la ligne en cours d'exécution et pour pouvoir afficher ou modifier une variable. Ces informations sont ajoutées à l'exécutable au moment de la compilation. GCC dispose de deux commutateurs ("switches") pour cela :

gcc -g -o monprog monprog.c

Cette option fournit les informations de débogage dans le format natif de votre système.

gcc -ggdb -o monprog monprog.c

Cette option va produire de l'information dans le format le plus détaillé pour GDB. Dans le cas d'AmigaOS 4.1, c'est cette option qui nous intéresse. Le niveau de détail peut être spécifié, ce niveau allant de 1 à 3, le défaut étant 2 :

gcc -ggdb3 -o monprog monprog.c

Bien que GDB soit un des rares débogueurs capable de s'en sortir avec des exécutables optimisés, il n'est pas recommandé d'activer les optimisations pour le débogage, donc pas d'option "-O".

3. GDB - peut-on en profiter ?

Bon, j'ai vendu le bazar, il y a bien un GDB (6.3) disponible, mais à la date d'aujourd'hui (15 novembre 2009), avec une Sam440ep utilisant AmigaOS 4.1 et le SDK 53.15, GDB n'est pas pleinement opérationnel, il manque quelques fonctionnalités qui rendent le débogage bien moins facile (possible ?). Je vais donc faire le tour de ce qui est utilisable actuellement.

4. GDB - dans la pratique

Dans la pratique, toutes les commandes de GDB sont abréviables. Pour obtenir la liste des commandes, utilisez la commande "help" qui affiche des catégories sur lesquelles on peut appeler à nouveau "help" pour obtenir la liste des commandes concernées, lesquelles commandes dévoilent leurs détails à l'aide de la même commande "help".

Autre point pratique, la touche "Return" sans commande rappelle la commande précédente.

4.1 Chargement de GDB

Il y a deux façons de charger GDB, en l'appelant directement avec l'exécutable à déboguer :

11.Apps:Dev/CodeBench/Projets/Debug/tests> gdb test
GNU gdb 6.3 (AmigaOS build 20050719)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "ppc-amigaos"...
(gdb)

...ou en chargeant ensuite le fichier à déboguer :

11.Apps:Dev/CodeBench/Projets/Debug/tests> gdb
GNU gdb 6.3 (AmigaOS build 20050719)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "ppc-amigaos".
(gdb) file test
Reading symbols from /Apps/Dev/CodeBench/Projets/Debug/tests/test...done.
(gdb)

Pour quitter, utiliser "quit" (q).

4.2 Lancement et passage de paramètres

L'exécution est lancée à l'aide de la commande "run" (r) :

(gdb) run
Starting program: /Files/Docs/Amiga/Articles/Gurumed/test1 
Hello world 

Program terminated with signal SIGQUIT, Quit.
The program no longer exists.
(gdb)

Si on a besoin de passer des paramètres sur la ligne de commandes, on les place derrière la comande "run" :

(gdb) run dumb et dumber
Starting program: /Files/Docs/Amiga/Articles/Gurumed/test1 dumb et dumber
Hello dumb et dumber  

Program terminated with signal SIGQUIT, Quit.
The program no longer exists.
(gdb)

Anomalie : quand on relance plusieurs fois un programme sans quitter GDB, celui-ci nous dit qu'un programme est déjà en cours d'exécution avant de le lancer. Il ne faut pas le croire, ce sont des balivernes :

(gdb) run dumb et dumber
Starting program: /Files/Docs/Amiga/Articles/Gurumed/test1 dumb et dumber
A program is already running:
        `/Files/Docs/Amiga/Articles/Gurumed/test1', file type elf32-amiga. 
        Entry point: 0x1000074
        0x01000074 - 0x01000380 is .text
        0x01001000 - 0x01001030 is .rodata
        0x01010000 - 0x01010008 is .ctors
        0x01010008 - 0x01010010 is .dtors
        0x01010010 - 0x01010014 is .sdata
        0x01010014 - 0x01010038 is .sbss
Hello dumb et dumber 

Program terminated with signal SIGQUIT, Quit.
The program no longer exists.
(gdb)

Point particulier : GDB garde les derniers arguments qu'on lui a fournis. Pour les voir, utiliser la commande "show args", pour s'en débarrasser, utiliser "set args".

4.3 Utilisation des points d'arrêt

Les points d'arrêt peuvent être positionnés au moyen de la commande "break" (b) suivie d'un nom de fonction ou d'un numéro de ligne dans un fichier. On peut examiner les points d'arrêt avec "info breakpoints" (ib) :

(gdb) b PrintArgs
Breakpoint 1 at 0x6fc73208: file test1.c, line 4.
(gdb) b 27
Breakpoint 2 at 0x6fc732e8: file test1.c, line 27.
(gdb) b test1.c:9
Breakpoint 3 at 0x6fc73230: file test1.c, line 9.
(gdb) i b
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x6fc73208 in PrintArgs at test1.c:4
2   breakpoint     keep y   0x6fc732e8 in main at test1.c:27
3   breakpoint     keep y   0x6fc73230 in PrintArgs at test1.c:9
(gdb)

Les points d'arrêts peuvent être retirés avec "clear" (cl) et leur localisation ou "delete" (d) et leur identifiant. Ils peuvent être désactivés et réactivés au moyen des commandes "disable" et "enable" suivies de leur identifiant.

Si on désire positionner un point d'arrêt utilisé une seule fois, on utilise "tbreak" (tb) qui positionne un point qui sera effacé automatiquement la première fois qu'il sera atteint.

Bon, GDB s'arrête sur un point d'arrêt, et après ? Ben pour repartir, il faut utiliser la commande "continue" (c). Problème, avec le SDK 53.15 d'AmigaOS 4.1 sur Sam440ep, dès que GDB s'arrête sur un point d'arrêt permanent, il oublie ensuite de s'arrêter sur quelque condition que ce soit, b, tb ou adv. Il reste donc la solution de ne travailler qu'avec des points d'arrêts temporaires ou des commandes "advance" abordées plus loin.

4.4 Exécution pas à pas

S'arrêter sur un point d'arrêt et repartir c'est bien, s'arrêter et poursuivre au ralenti, c'est mieux. GDB propose deux types de commandes pas à pas, "next" (n) et "step" (s).
  • "next" passe à la ligne suivante du source, sans descendre dans les appels de fonction.
  • "step" passe à l'instruction suivante, en descendant dans les appels de fonction.
  • "finish" sort de la fonction en cours et retourne au point d'appel.
Le problème, c'est qu'avec le SDK 53.15 sur Sam440ep, "next" et "step" boudent et font la même chose que "continue". Un débugueur sans mode pas à pas, c'est diablement moins intéressant.

4.5 Exécution jusque...

Pour contrôler l'exécution de notre programme, il y a encore la commande "advance" (adv) qui prend en argument une identification de ligne identique à la définition d'un point d'arrêt. On peut voir cette commande comme la combinaison du positionnement d'un point d'arrêt temporaire et la commande "continue".

Bonne nouvelle, cette commande semble fonctionner presque correctement... à condition de ne pas utiliser un point d'arrêt permanent et à condition de ne pas jouer dans des boucles.

4.6 L'examen des variables

4.6.1 Le type des variables

On peut demander à GDB de nous rappeler le type d'une variable avec la commande "ptype" (pt) :

(gdb) ptype idx
type = int
(gdb) t

4.6.2 Examen occasionnel

Quand on a besoin d'examiner une variable, on utilise la commande "print" (p).

(gdb) p argc
$1 = 1
(gdb) p argv[1]
$5 = 0x50dc1b20 "toto"
(gdb)

Bonne nouvelle, il existe également une commande "printf".

(gdb) printf "argv[%d]=\"%s\"\n", 0, argv[0]
argv[0]="gdb"
(gdb)

On peut également typer une variable à la volée si nécessaire ou spécifier le format d'affichage avec :
  • /o pour octal
  • /x pour hexadécimal
  • /d pour décimal
  • /u pour unsigned decimal
  • /t pour binaire
  • /f pour flottant
  • /a pour adresse
  • /c pour caractère
4.6.3 Examen permanent

Quand on a besoin de suivre une variable au cours d'une exécution, la commande "display" (disp ) permet d'afficher le contenu d'une variable à chaque arrêt d'exécution.

(gdb) disp idx
1: idx = 1
(gdb) c
Continuing.
BS 52e2c5d0
Current action: 2
PrintArgs (count=4, argv=0x52d8ab58) at test1.c:11
11      }
1: idx = 4
(gdb)

4.6.4 La modification de variable

Les variables peuvent également être modifiées à l'aide de la commande "set variable" abréviable par "set" (<expression>) :

(gdb) p argc
$3 = 4
(gdb) set variable argc = 1
(gdb) p argc                
$4 = 1
(gdb) set (argc = 2)
(gdb) p argc         
$5 = 2
(gdb)

4.6.5 La surveillance de variable

La commande "watch" (wa) permet de surveiller une variable (ou une expression) et d'arrêter l'exécution si une instruction modifie la variable (ou vérifie l'expression), ce qui peut être très intéressant pour localiser la modification fortuite d'une variable. Bon, dans la pratique, ça ne fonctionne pas avec notre SDK, étonnant, non ?

Il existe des variantes "rwatch" et "awatch" qui surveillent respectivement l'accès en lecture ou l'accès en lecture ou écriture, mais elles ne sont pas gérées par notre plate-forme. Bref, point de salut ici.

4.7 Visualisation du source

La commande "list" (l) permet d'afficher 10 lignes centrées sur la ligne d'exécution courante. Les appels suivants à "list" affichent les 10 lignes suivantes et ainsi de suite. Pour remonter dans le source, on utilise "list -". Pour lister une ligne précise, on l'indique derrière "list". Pour se localiser, la commande "where" affiche une pile d'appel simplifiée.

(gdb) where
#0  PrintArgs (count=4, argv=0x56536b40) at test1.c:7
#1  0x6fc72344 in main (argc=4, argv=0x56536b40) at test1.c:34
(gdb)

4.8 La pile d'appel

En plus de "where", la pile des appels de fonction en cours peut être affichée au moyen de la commande "backtrace" (bt).

(gdb) bt
#0  PrintArgs (count=4, argv=0x49c30b48) at test1.c:9
trad_frame_addr_p: 1
trad_frame_realreg_p: 0
trad_frame_value_p: 0
alt 1
#1  0x6fc732d4 in main (argc=4, argv=0x49c30b48) at test1.c:20
(gdb)

Le niveau 0 est la fonction en cours (PrintArgs) qui a été appelée depuis le niveau 1 (main), et ainsi de suite.

Les commandes "up" et "down" permettent de se déplacer dans la pile d'appel afin d'avoir accès au contexte de pile concerné, pour examiner les variables automatiques par exemple.

(gdb) up
#1  0x6fc72344 in main (argc=4, argv=0x56536b40) at test1.c:34
34                      PrintArgs(argc, argv);
(gdb) down
#0  PrintArgs (count=4, argv=0x56536b40) at test1.c:7
7               for(idx = 1; idx < count; ++idx)
(gdb)

4.9 L'attachement à un processus

L'attachement à un processus peut être très intéressant pour inspecter l'état d'un processus en cours d'exécution. Un exemple qui me vient à l'idée serait de s'attacher au processus d'un serveur Ftp pour le déboguer en direct. Bon, je n'ai pas réussi à m'attacher à un processus, là aussi pas de surprise.

5. En conclusion

GDB est-il d'un grand secours en l'état actuel des choses ? Bonne question.

On peut tenter un débogage à l'aide de points d'arrêts temporaires, de commandes "advance", d'affichage de variable et de modification de variable. Cela n'apporte pas beaucoup plus que des "printf()", mais ça permet d'adapter ce qu'on veut voir et où on veut aller pendant l'exécution du programme, sans avoir besoin d'arrêter, de modifier le source et de recompiler. Cela peut donc être un petit peu mieux que des "printf()" mais il y a des cas, comme les boucles, où GDB ne s'arrêtera que la première fois. Il faudra donc envisager un doux mélange de "printf()" et de débogage.

Si maintenant on se demande si les développeurs disposent de bons outils pour mettre au point leurs développements, ma réponse est clairement : NON. A tître de comparaison, lorsque je développe sous Delphi, le débogueur intégré arrête sur la ligne ayant déclenché une exception. Si la cause ne saute pas aux yeux, j'inspecte la pile d'appel, je mets un point d'arrêt en amont, je relance le bazarre, arrivé sur mon point d'arrêt j'inspecte les variables intéressantes en m'approchant du point d'exception jusqu'à localiser l'anomalie. Dans la pratique, je localise la cause immédiatement ou en quelques minutes, ce qui me permet d'utiliser mon temps à concevoir plutôt qu'à chercher la fichue ligne qui a déclenché un bête accès mémoire illégal.

Mon temps sur Amiga étant pris sur mon temps libre, j'ai encore plus besoin d'efficacité dans mes développements que pour mon boulot. Alors s'il vous plait, donnez nous des outils qui fonctionnent.


[Retour en haut] / [Retour aux articles]