Posso definir um ponto de interrupção no 'acesso à memória' no GDB?

244

Estou executando um aplicativo por meio do gdb e quero definir um ponto de interrupção sempre que uma variável específica for acessada / alterada. Existe um bom método para fazer isso? Também estaria interessado em outras maneiras de monitorar uma variável em C / C ++ para ver se / quando ela muda.

TJ Seabrooks
fonte

Respostas:

286

assistir apenas pausas na gravação, rwatch permite interromper a leitura e despertar permitir interromper a leitura / gravação.

Você pode definir pontos de controle de leitura em locais de memória:

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

mas uma limitação se aplica aos comandos rwatch e awatch; você não pode usar variáveis ​​gdb em expressões:

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

Então você tem que expandi-los você mesmo:

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: Ah, e por falar nisso. Você precisa de suporte de hardware ou software . O software é obviamente muito mais lento. Para descobrir se o seu sistema operacional suporta pontos de controle de hardware, você pode ver a configuração do ambiente can-use-hw-watchpoints .

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
askol
fonte
7
Se você quiser assistir a um membro de método de um C ++, eu encontrei esta variante imensamente útil: watch -location mTextFormatted.
Ivan Vučica
E se eu não tiver o endereço de uma variável? Posso apenas usar o nome dele?
Raffi Khatchadourian
5
Você pode fazer com que o GDB imprima o endereço da variável com o endereço do operador. print &variable
Loduwijk
1
Esta resposta não diz nada sobre o tamanho da localização da memória que está sendo observada por watchcomandos. Enquanto isso, esta é a primeira pergunta que vem à mente depois de ler o acima. Quantos bytes rwatch *0xfeedfacerealmente assistirão?
AnT
8
@ Ant, eu estava assumindo que assistiria a um único byte, o que parece ser o caso, mas você pode convertê- lo para um tipo específico, por exemplo, rwatch *(int *)0xfeedfacee ele assistirá sizeof(int)bytes: sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints. html
askol
28

O que você está procurando é chamado de ponto de controle .

Uso

(gdb) watch foo: observe o valor da variável foo

(gdb) watch *(int*)0x12345678: observe o valor apontado por um endereço , transmitido para o tipo que você deseja

(gdb) watch a*b + c/d: assista a uma expressão arbitrariamente complexa , válida no idioma nativo do programa

Os watchpoints são de três tipos:

  • watch : o gdb será interrompido quando ocorrer uma gravação
  • rwatch : gdb vai quebrar wnen uma leitura ocorre
  • awatch : o gdb será interrompido nos dois casos

Você pode escolher o mais apropriado para suas necessidades.

Para mais informações, verifique isso .

Paolo M
fonte
5
Eu escrevi outra resposta porque os existentes não parecia muito simples para mim ...
Paolo M
25

Supondo que a primeira resposta esteja se referindo à sintaxe do tipo C (char *)(0x135700 +0xec1a04f), a resposta a ser feita rwatch *0x135700+0xec1a04festá incorreta. A sintaxe correta é rwatch *(0x135700+0xec1a04f).

A falta de ()s lá me causou muita dor ao tentar usar os pontos de controle.

Smirnov
fonte
9

Eu apenas tentei o seguinte:

 $ 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

Parece possível, mas você parece precisar de algum suporte de hardware.

Mweerden
fonte
Se a sua plataforma não suportar os watchpoints de hardware, o gdb deverá voltar a um watch point de software.
Tod
2

Use watch para ver quando uma variável é gravada, rwatch quando for lida e desperte quando for lida / gravada de / para, conforme observado acima. No entanto, observe que, para usar este comando, é necessário interromper o programa e a variável deve estar no escopo quando você o interromper:

Use o comando watch. O argumento para o comando watch é uma expressão que é avaliada. Isso implica que a variável na qual você deseja definir um ponto de controle deve estar no escopo atual. Portanto, para definir um ponto de controle em uma variável não global, você deve ter definido um ponto de interrupção que interrompa seu programa quando a variável estiver no escopo. Você define o ponto de controle após a interrupção do programa.

higgs241
fonte