Bisakah saya menetapkan breakpoint pada 'akses memori' di GDB?

244

Saya menjalankan aplikasi melalui gdb dan saya ingin menetapkan breakpoint kapan saja variabel tertentu diakses / diubah. Apakah ada metode yang baik untuk melakukan ini? Saya juga tertarik dengan cara lain untuk memonitor variabel dalam C / C ++ untuk melihat apakah / ketika itu berubah.

TJ Seabrooks
sumber

Jawaban:

286

menonton hanya istirahat pada menulis, jam tangan Anda istirahat membaca, dan menonton membiarkan Anda istirahat membaca / menulis.

Anda dapat mengatur titik pantau baca di lokasi memori:

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

tetapi satu batasan berlaku untuk perintah rwatch dan awatch; Anda tidak dapat menggunakan variabel gdb dalam ekspresi:

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

Jadi, Anda harus mengembangkannya sendiri:

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

Sunting: Oh, dan omong-omong. Anda memerlukan dukungan perangkat keras atau perangkat lunak . Perangkat lunak jelas jauh lebih lambat. Untuk mengetahui apakah OS Anda mendukung titik pandang perangkat keras, Anda dapat melihat pengaturan lingkungan titik penggunaan dapat-hw .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
askol
sumber
7
Jika Anda ingin menonton anggota dari metode C ++, saya menemukan varian ini sangat berguna: watch -location mTextFormatted.
Ivan Vučica
Bagaimana jika saya tidak memiliki alamat variabel? Bisakah saya menggunakan namanya saja?
Raffi Khatchadourian
5
Anda dapat meminta GDB mencetak alamat variabel dengan alamat-operator. print &variable
Loduwijk
1
Jawaban ini tidak mengatakan apa pun tentang ukuran lokasi memori yang dipantau oleh watchperintah. Sementara itu, ini adalah pertanyaan pertama yang muncul di pikiran setelah membaca di atas. Berapa banyak byte yang rwatch *0xfeedfaceakan ditonton?
AnT
8
@ ANT, saya berasumsi itu akan menonton satu byte, yang tampaknya menjadi kasus, tetapi Anda dapat melemparkannya ke jenis tertentu misalnya rwatch *(int *)0xfeedfacedan akan menonton sizeof(int)byte: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints. html
askol
28

Apa yang Anda cari disebut titik jaga .

Pemakaian

(gdb) watch foo: perhatikan nilai variabel foo

(gdb) watch *(int*)0x12345678: perhatikan nilai yang ditunjukkan oleh alamat , dicantumkan ke jenis apa pun yang Anda inginkan

(gdb) watch a*b + c/d: saksikan ekspresi kompleks yang sewenang-wenang , valid dalam bahasa ibu program

Arloji ada tiga macam:

  • menonton : gdb akan mematahkan ketika menulis terjadi
  • rwatch : gdb akan pecah ketika terjadi pembacaan
  • awatch : gdb akan pecah di kedua kasus

Anda dapat memilih yang lebih sesuai dengan kebutuhan Anda.

Untuk informasi lebih lanjut, lihat ini .

Paolo M
sumber
5
Saya menulis jawaban lain karena yang sudah ada sepertinya tidak mudah bagi saya ...
Paolo M
25

Dengan asumsi jawaban pertama mengacu pada sintaks mirip C (char *)(0x135700 +0xec1a04f)maka jawaban yang harus dilakukan rwatch *0x135700+0xec1a04fsalah. Sintaks yang benar adalah rwatch *(0x135700+0xec1a04f).

Kurangnya ()ada di sana menyebabkan saya sangat sakit mencoba menggunakan watchpoints sendiri.

Smirnov
sumber
9

Saya baru saja mencoba yang berikut ini:

 $ 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

Jadi sepertinya mungkin, tetapi Anda tampaknya memerlukan dukungan perangkat keras.

mweerden
sumber
Jika platform Anda tidak mendukung titik pandang perangkat keras, gdb akan kembali ke titik pengawasan perangkat lunak.
Tod
2

Gunakan arloji untuk melihat kapan suatu variabel ditulis, lihat kapan itu dibaca dan baca ketika itu dibaca / ditulis dari / ke, seperti disebutkan di atas. Namun, harap dicatat bahwa untuk menggunakan perintah ini, Anda harus merusak program, dan variabel harus berada dalam cakupan ketika Anda telah merusak program:

Gunakan perintah arloji. Argumen untuk perintah arloji adalah ekspresi yang dievaluasi. Ini menyiratkan bahwa variabel yang ingin Anda setel titik jaga harus dalam lingkup saat ini. Jadi, untuk menetapkan titik tontonan pada variabel non-global, Anda harus menetapkan titik istirahat yang akan menghentikan program Anda ketika variabel berada dalam cakupan. Anda mengatur titik tonton setelah program istirahat.

higgs241
sumber