Czy mogę ustawić punkt przerwania dla „dostępu do pamięci” w GDB?

244

Uruchamiam aplikację za pośrednictwem gdb i chcę ustawić punkt przerwania za każdym razem, gdy konkretna zmienna jest dostępna / zmieniana. Czy jest na to dobra metoda? Byłbym również zainteresowany innymi sposobami monitorowania zmiennej w C / C ++, aby zobaczyć, czy / kiedy się zmienia.

TJ Seabrooks
źródło

Odpowiedzi:

286

oglądaj tylko przerwy w trakcie pisania, rwatch pozwala na przerwanie podczas odczytu, a awatch pozwala na przerwanie podczas odczytu / zapisu.

Możesz ustawić odczytane punkty obserwacyjne w lokalizacjach pamięci:

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

ale jedno ograniczenie dotyczy poleceń zegarka i awatera; nie możesz używać zmiennych gdb w wyrażeniach:

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

Więc musisz je rozwinąć:

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 ()

Edycja: A tak przy okazji. Potrzebujesz wsparcia sprzętowego lub programowego . Oprogramowanie jest oczywiście znacznie wolniejsze. Aby dowiedzieć się, czy Twój system operacyjny obsługuje sprzętowe punkty obserwacyjne, możesz zobaczyć ustawienie środowiska can-use-hw-watchpoints .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
pyta
źródło
7
Jeśli chcesz oglądać członek metody C ++, znalazłem ten wariant niezmiernie przydatne: watch -location mTextFormatted.
Ivan Vučica
Co jeśli nie mam adresu zmiennej? Czy mogę po prostu użyć jego nazwy?
Raffi Khatchadourian
5
Możesz poprosić GDB o wydrukowanie adresu zmiennej za pomocą adresu operatora. print &variable
Loduwijk
1
Ta odpowiedź nie mówi nic o wielkości lokalizacji pamięci obserwowanej przez watchpolecenia. Tymczasem jest to pierwsze pytanie, które przychodzi mi do głowy po przeczytaniu powyższego. Ile bajtów rwatch *0xfeedfacefaktycznie obejrzy?
AnT
8
@AnT, zakładałem, że obejrzy pojedynczy bajt, co wydaje się być w rzeczywistości, ale możesz go przerzucić na określony typ, np. rwatch *(int *)0xfeedfaceI będzie on oglądać sizeof(int)bajty: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints. html
pyta
28

To, czego szukasz, nazywa się punktem obserwacyjnym .

Stosowanie

(gdb) watch foo: obserwuj wartość zmiennej foo

(gdb) watch *(int*)0x12345678: obserwuj wartość wskazywaną przez adres , rzutowaną na dowolny typ

(gdb) watch a*b + c/d: obejrzyj dowolnie złożone wyrażenie , poprawne w języku ojczystym programu

Punkty obserwacyjne są trzech rodzajów:

  • watch : gdb ulegnie awarii, gdy nastąpi zapis
  • rwatch : gdb zepsuje się, gdy nastąpi odczyt
  • awatch : gdb ulegnie awarii w obu przypadkach

Możesz wybrać bardziej odpowiedni dla swoich potrzeb.

Aby uzyskać więcej informacji, sprawdź to .

Paolo M.
źródło
5
Napisałem inną odpowiedź, ponieważ istniejące nie wydawały mi się zbyt proste ...
Paolo M
25

Zakładając, że pierwsza odpowiedź odnosi się do składni podobnej do C, (char *)(0x135700 +0xec1a04f)wówczas odpowiedź do wykonania rwatch *0x135700+0xec1a04fjest niepoprawna. Prawidłowa składnia to rwatch *(0x135700+0xec1a04f).

Brak ()s sprawił mi wiele bólu, próbując samemu korzystać z punktów obserwacyjnych.

Smirnov
źródło
9

Właśnie wypróbowałem następujące:

 $ 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

Wydaje się to możliwe, ale wydaje się, że potrzebujesz wsparcia sprzętowego.

Mweerden
źródło
Jeśli twoja platforma nie obsługuje sprzętowych punktów obserwacyjnych, gdb powinien wrócić do punktu obserwacyjnego oprogramowania.
Tod
2

Użyj zegarka, aby zobaczyć, kiedy zmienna jest zapisywana do, rwatch, gdy zostanie odczytana, i czuj, gdy zostanie odczytana / zapisana z / do, jak wspomniano powyżej. Należy jednak pamiętać, że aby użyć tego polecenia, musisz przerwać program, a zmienna musi mieć zasięg, gdy program zostanie uszkodzony:

Użyj polecenia oglądania. Argument polecenia watch jest wyrażeniem, które jest obliczane. Oznacza to, że zmienna, na której chcesz ustawić punkt obserwacyjny, musi mieć bieżący zakres. Tak więc, aby ustawić punkt obserwacyjny dla zmiennej nieglobalnej, musisz ustawić punkt przerwania, który zatrzyma program, gdy zmienna będzie w zasięgu. Punkt kontrolny ustawia się po zerwaniu programu.

higgs241
źródło