Puis-je définir un point d'arrêt sur «l'accès à la mémoire» dans GDB?

244

J'exécute une application via gdb et je veux définir un point d'arrêt pour chaque fois qu'une variable spécifique est accédée / modifiée. Existe-t-il une bonne méthode pour ce faire? Je serais également intéressé par d'autres façons de surveiller une variable en C / C ++ pour voir si / quand elle change.

TJ Seabrooks
la source

Réponses:

286

ne regardez que les pauses en écriture, rwatch vous permet de faire une pause en lecture et awatch vous permet de pauses en lecture / écriture.

Vous pouvez définir des points de lecture sur les emplacements de mémoire:

gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface

mais une limitation s'applique aux commandes rwatch et awatch; vous ne pouvez pas utiliser de variables gdb dans les expressions:

gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.

Vous devez donc les développer vous-même:

gdb$ print $ebx 
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f

Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()

Edit: Oh, et au fait. Vous avez besoin d'un support matériel ou logiciel . Le logiciel est évidemment beaucoup plus lent. Pour savoir si votre système d'exploitation prend en charge les points de surveillance matériels, vous pouvez voir le paramètre d'environnement can-use-hw-watchpoints .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
askol
la source
7
Si vous voulez regarder un membre de la méthode d'un C, j'ai trouvé cette variante extrêmement utile: watch -location mTextFormatted.
Ivan Vučica
Et si je n'ai pas l'adresse d'une variable? Puis-je simplement utiliser son nom?
Raffi Khatchadourian
5
Vous pouvez demander à GDB d'imprimer l'adresse de la variable avec l'opérateur d'adresse. print &variable
Loduwijk
1
Cette réponse ne dit rien sur la taille de l'emplacement mémoire surveillé par les watchcommandes. En attendant, c'est la première question qui me vient à l'esprit après avoir lu ce qui précède. Combien d'octets rwatch *0xfeedfaceregarderont réellement?
2015
8
@AnT, je supposais qu'il regarderait un seul octet, ce qui semble être le cas, mais vous pouvez le convertir en un type spécifique, par exemple, rwatch *(int *)0xfeedfaceet il regardera les sizeof(int)octets: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints. html
askol
28

Ce que vous recherchez s'appelle un point d' observation .

Usage

(gdb) watch foo: surveiller la valeur de la variable foo

(gdb) watch *(int*)0x12345678: regardez la valeur pointée par une adresse , castée dans le type que vous voulez

(gdb) watch a*b + c/d: regarder une expression arbitrairement complexe , valide dans la langue maternelle du programme

Les points d'observation sont de trois types:

  • watch : gdb se cassera lorsqu'une écriture se produit
  • rwatch : gdb se cassera quand une lecture aura lieu
  • awatch : gdb se cassera dans les deux cas

Vous pouvez choisir le plus approprié à vos besoins.

Pour plus d'informations, consultez ceci .

Paolo M
la source
5
J'ai écrit une autre réponse parce que les réponses existantes ne me semblaient pas très simples ...
Paolo M
25

En supposant que la première réponse se réfère à la syntaxe de type C, (char *)(0x135700 +0xec1a04f)la réponse à faire rwatch *0x135700+0xec1a04fest incorrecte. La syntaxe correcte est rwatch *(0x135700+0xec1a04f).

Le manque de ()s là m'a causé beaucoup de douleur en essayant d'utiliser moi-même les points d'observation.

Smirnov
la source
9

Je viens d'essayer ce qui suit:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

Cela semble donc possible, mais vous semblez avoir besoin d'un support matériel.

mweerden
la source
Si votre plate-forme ne prend pas en charge les points de surveillance matériels, la gdb devrait revenir à un point de surveillance logicielle.
Tod
2

Utilisez watch pour voir quand une variable est écrite, rwatch lorsqu'elle est lue et awatch lorsqu'elle est lue / écrite de / vers, comme indiqué ci-dessus. Cependant, veuillez noter que pour utiliser cette commande, vous devez interrompre le programme et la variable doit être dans la portée lorsque vous avez interrompu le programme:

Utilisez la commande watch. L'argument de la commande watch est une expression qui est évaluée. Cela implique que le variabel sur lequel vous souhaitez définir un point de surveillance doit être dans la portée actuelle. Ainsi, pour définir un point de surveillance sur une variable non globale, vous devez avoir défini un point d'arrêt qui arrêtera votre programme lorsque la variable est dans la portée. Vous définissez le point d'observation après l'interruption du programme.

higgs241
la source