jonesforth est généralement commencé comme suit:Comment déboguer jonesforth avec GDB?
cat jonesforth.f - | ./jonesforth
Qu'est-ce qu'un bon moyen de déboguer jonesforth
?
jonesforth est généralement commencé comme suit:Comment déboguer jonesforth avec GDB?
cat jonesforth.f - | ./jonesforth
Qu'est-ce qu'un bon moyen de déboguer jonesforth
?
Si vous êtes sur Ubuntu, permettent gdb
d'attacher aux processus en cours d'exécution:
echo 0 > /proc/sys/kernel/yama/ptrace_scope
Si vous souhaitez que l'établissement de rester entre les redémarrages:
vim /etc/sysctl.d/10-ptrace.conf
Ajouter le drapeau g
à votre jonesforth
Makefile
recette:
jonesforth: jonesforth.S
gcc -g -m32 -nostdlib -static $(BUILD_ID_NONE) -o [email protected] $<
Ensuite, démarrez jonesforth comme d'habitude dans un terminal:
cat jonesforth.f - | ./jonesforth
Dans un autre terminal, commencez gdb
et l'attacher à la jonesforth en cours d'exécution:
gdb --quiet --pid=`pgrep jonesforth` ./jonesforth
Voici ce que je vois quand je commence gdb
:
$ gdb --quiet --pid=`pgrep jonesforth` ./jonesforth
Reading symbols from ./jonesforth...done.
Attaching to program: /home/dharmatech/Dropbox/Documents/jonesforth-annexia/jonesforth, process 3406
_KEY() at jonesforth.S:1290
1290 test %eax,%eax // If %eax <= 0, then exit.
(gdb)
Jonesforth nous attend d'entrer quelque chose. C'est dans la routine d'assemblage _KEY
. Ceci est indiqué par gdb
ci-dessus. Il montre également que la ligne 1290 est la suivante à exécuter. Voici la routine _KEY
:
_KEY:
mov (currkey),%ebx
cmp (bufftop),%ebx
jge 1f // exhausted the input buffer?
xor %eax,%eax
mov (%ebx),%al // get next key from input buffer
inc %ebx
mov %ebx,(currkey) // increment currkey
ret
1: // Out of input; use read(2) to fetch more input from stdin.
xor %ebx,%ebx // 1st param: stdin
mov $buffer,%ecx // 2nd param: buffer
mov %ecx,currkey
mov $BUFFER_SIZE,%edx // 3rd param: max length
mov $__NR_read,%eax // syscall: read
int $0x80
test %eax,%eax // If %eax <= 0, then exit.
jbe 2f
addl %eax,%ecx // buffer+%eax = bufftop
mov %ecx,bufftop
jmp _KEY
2: // Error or end of input: exit the program.
xor %ebx,%ebx
mov $__NR_exit,%eax // syscall: exit
int $0x80
_KEY
utilise des variables en mémoire: buffer
, currkey
et bufftop
. Il utilise également quelques registres. Utilisons fonction de Auto Display
gdb
pour afficher celles-ci:
display/8cb &buffer
display/1xw &currkey
display/1xw &bufftop
display/x $eax
display/x $ebx
Maintenant, si nous tapons display
à gdb
, nous verrons tous ceux à la fois:
(gdb) display
1: x/8cb &buffer
0x804c000: 97 'a' 98 'b' 108 'l' 121 'y' 46 '.' 32 ' ' 32 ' ' 84 'T'
2: x/xw &currkey 0x8049d54: 0x0804c000
3: x/xw &bufftop 0x8049d58: 0x0804c7e3
4: /x $eax = 0xfffffe00
5: /x $ebx = 0x0
Cela pourrait être aussi un bon moment pour permettre la TUI « gdb
:
tui enable
gdb devrait ressembler à ceci:
OK, jonesforth attend toujours l'entrée.Donc, nous allons lui donner quelque chose:
JONESFORTH VERSION 47
14499 CELLS REMAINING
OK 123
Bon, retour à gdb, on peut enfin demander à l'étape:
(gdb) s
1: x/8cb &buffer
0x804c000: 49 '1' 50 '2' 51 '3' 10 '\n' 46 '.' 32 ' ' 32 ' ' 84 'T'
2: x/xw &currkey 0x8049d54: 0x0804c000
3: x/xw &bufftop 0x8049d58: 0x0804c7e3
4: /x $eax = 0x4
5: /x $ebx = 0x0
Hé, regardez ça! Les 3 premiers caractères de buffer
sont 1
, 2
et 3
.
Si %eax <= 0
, l'étape suivante passera à l'étiquette 2f
. Mais comme nous pouvons le voir ci-dessus, %eax
est 4
. Cela devrait donc continuer.
Si nous franchissons les trois lignes suivantes, le bufftop
sera défini sur l'adresse buffer
incrémentée de 4 (trois caractères de '123' plus un caractère de nouvelle ligne). La valeur par rapport à l'adresse de buffer
vérifie:
3: x/xw &bufftop 0x8049d58: 0x0804c004
Maintenant que les données ont été lues dans le tampon d'entrée, _KEY
fera son travail et revenir à l'appelant. Voici les instructions PROCHAINS avant le retour:
Comme vous l'étape par ceux-ci, la fonction d'affichage automatique affiche les variables et la mise à jour des registres en conséquence.