Kann ich in GDB einen Haltepunkt für 'Speicherzugriff' festlegen?

244

Ich führe eine Anwendung über gdb aus und möchte einen Haltepunkt für jedes Mal festlegen, wenn auf eine bestimmte Variable zugegriffen / diese geändert wird. Gibt es dafür eine gute Methode? Ich würde mich auch für andere Möglichkeiten interessieren, eine Variable in C / C ++ zu überwachen, um festzustellen, ob / wann sie sich ändert.

TJ Seabrooks
quelle

Antworten:

286

Beobachten Sie nur Pausen beim Schreiben, Rwatch lässt Sie beim Lesen brechen und Awatch lässt Sie beim Lesen / Schreiben brechen.

Sie können Leseüberwachungspunkte an Speicherorten festlegen:

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

Eine Einschränkung gilt jedoch für die Befehle rwatch und awatch. Sie können keine GDB-Variablen in Ausdrücken verwenden:

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

Sie müssen sie also selbst erweitern:

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, und übrigens. Sie benötigen entweder Hardware- oder Softwareunterstützung . Software ist offensichtlich viel langsamer. Um herauszufinden, ob Ihr Betriebssystem Hardware-Überwachungspunkte unterstützt, sehen Sie die Umgebungseinstellung can-use-hw-watchpoints .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
fragtol
quelle
7
Wenn Sie ein Mitglied einer C ++ - Methode sehen möchten, fand ich diese Variante äußerst nützlich : watch -location mTextFormatted.
Ivan Vučica
Was ist, wenn ich nicht die Adresse einer Variablen habe? Kann ich nur seinen Namen verwenden?
Raffi Khatchadourian
5
Sie können GDB die Adresse der Variablen mit dem Operator address-of drucken lassen. print &variable
Loduwijk
1
Diese Antwort sagt nichts über die Größe des Speicherorts aus, der von watchBefehlen überwacht wird . In der Zwischenzeit ist dies die erste Frage, die nach dem Lesen der obigen Informationen in den Sinn kommt. Wie viele Bytes rwatch *0xfeedfacewerden tatsächlich angezeigt?
Am
8
@AnT, ich ging davon aus, dass es ein einzelnes Byte anzeigen würde, was der Fall zu sein scheint, aber Sie können es in einen bestimmten Typ umwandeln, z. B. rwatch *(int *)0xfeedfaceund es werden sizeof(int)Bytes überwacht
fragtol
28

Was Sie suchen, wird als Überwachungspunkt bezeichnet .

Verwendung

(gdb) watch foo: Beobachten Sie den Wert der Variablen foo

(gdb) watch *(int*)0x12345678: Beobachten Sie den Wert, auf den eine Adresse zeigt , die in einen beliebigen Typ umgewandelt wurde

(gdb) watch a*b + c/d: Beobachten Sie einen beliebig komplexen Ausdruck , der in der Muttersprache des Programms gültig ist

Es gibt drei Arten von Überwachungspunkten:

  • watch : gdb wird beim Schreiben unterbrochen
  • rwatch : GDB bricht wnen eine Lese auftritt
  • awatch : gdb wird in beiden Fällen kaputt gehen

Sie können die für Ihre Bedürfnisse geeignetere auswählen.

Für weitere Informationen besuchen Sie diese aus.

Paolo M.
quelle
5
Ich schrieb eine andere Antwort, weil mir bestehende nicht sehr einfach erschienen ...
Paolo M
25

Angenommen, die erste Antwort bezieht sich auf die C-ähnliche Syntax, (char *)(0x135700 +0xec1a04f)dann ist die zu erledigende Antwort rwatch *0x135700+0xec1a04ffalsch. Die richtige Syntax lautet rwatch *(0x135700+0xec1a04f).

Das Fehlen von ()s dort verursachte mir große Schmerzen beim Versuch, selbst Überwachungspunkte zu verwenden.

Smirnov
quelle
9

Ich habe gerade Folgendes versucht:

 $ 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

Es scheint also möglich, aber Sie scheinen Hardware-Unterstützung zu benötigen.

mweerden
quelle
Wenn Ihre Plattform keine Hardware-Überwachungspunkte unterstützt, sollte die GDB auf einen Software-Überwachungspunkt zurückgreifen.
Tod
2

Verwenden Sie watch, um zu sehen, wann eine Variable geschrieben wird, rwatch, wenn sie gelesen wird, und awatch, wenn sie von / nach gelesen / geschrieben wird, wie oben angegeben. Beachten Sie jedoch, dass Sie zur Verwendung dieses Befehls das Programm unterbrechen müssen und die Variable im Gültigkeitsbereich sein muss, wenn Sie das Programm unterbrochen haben:

Verwenden Sie den Befehl watch. Das Argument für den Befehl watch ist ein Ausdruck, der ausgewertet wird. Dies bedeutet, dass die Variable, für die Sie einen Überwachungspunkt festlegen möchten, im aktuellen Bereich liegen muss. Um einen Überwachungspunkt für eine nicht globale Variable festzulegen, müssen Sie einen Haltepunkt festgelegt haben, der Ihr Programm stoppt, wenn sich die Variable im Gültigkeitsbereich befindet. Sie legen den Überwachungspunkt fest, nachdem das Programm unterbrochen wurde.

higgs241
quelle