[轉]GDB-----2.watchpoint


TODO需要在ARM下驗證

1. 前言

watchpoint,顧名思義,其一般用來觀察某個變量/內存地址的狀態(也可以是表達式),如可以監控該變量/內存值是否被程序讀/寫情況。

在gdb中可通過下面的幾種方法來設置watchpoint:

    (gdb) watch 
        在指定變量/內存地址(表達式)expr設置一個watchpoint。
        一但expr值有變化時,將停住程序。
    (gdb) rwatch 
       當expr被讀時,停住程序。
    (gdb) awatch 
       當expr被讀或被寫時,停住程序。
    (gdb) info watchpoints 
        列出當前所設置了的所有觀察點。(info break也可查看)

2. gdb watchpoint實踐

GDB十分鍾快速入門教程的gdb-sample.c為例,
在gdb-sample.c中, 變量n總共被改變了3次,如果我們下個watchpoint在n變量處,因為n變量改變了3次而響應3次watchpoint,因而程序會將被調試器暫停運行3次:

編譯gdb-sample.c,並使用gdb 加載gdb-sample:


$ gcc gdb-sample.c -o gdb-sample -g 
$ gdb ./gdb-sample 
GNU gdb (GDB) 7.0.50.20090928-cvs 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type “show copying” 
and “show warranty” for details. 
This GDB was configured as “i686-pc-linux-gnu”. 
For bug reporting instructions, please see: 
… 
Reading symbols from /home/ddd/gdb-sample…done. 
(gdb) 

watchpoint只能在程序啟動后設置,先在main那下個斷點,讓程序啟動后暫停在main函數處:


(gdb) b main 
Breakpoint 1 at 0x80483ad: file gdb-sample.c, line 19. 
(gdb) r 
Starting program: /home/ddd/gdb-sample

 

Breakpoint 1, main () at gdb-sample.c:19 
19 n = 1; 
(gdb) 

給n變量下個watchpoint:


(gdb) watch n 
Hardware watchpoint 2: n 
(gdb) 

敲入”c”命令讓程序恢復運行,這時候程序會停止在第一次n變量改變處


20 n++; 

並提示即將運行的下一條的語句:


23 n--;

(gdb) c 
Continuing. 
Hardware watchpoint 2: n

 

Old value = -1208017424 
New value = 2 
main () at gdb-sample.c:23 
23 n--; 
(gdb) 

重復如上操作,程序還會停止兩次,所有gdb輸出如下:


(gdb) c 
Continuing. 
Hardware watchpoint 2: n

 

Old value = 2 
New value = 1 
main () at gdb-sample.c:25 
25 nGlobalVar += 100; 
(gdb) —-> 這次停止是由 ”23 n–; “改變變量n的值引起的

(gdb) c 
Continuing. 
n = 1, nGlobalVar = 88 
tempFunction is called, a = 1, b = 2 
Hardware watchpoint 2: n

Old value = 1 
New value = 3 
main () at gdb-sample.c:31 
31 printf(“n = %d”, n); 
(gdb) —-> 這次停止是由 ” 30 n = tempFunction(1, 2); “改變變量n的值引起的

(gdb) c 
Continuing.

Watchpoint 2 deleted because the program has left the block in 
which its expression is valid. 
0xb7e91450 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6 
(gdb) 

2: watchpoint在gdb中的實現原理

watchpoint可以看成是一種特殊的”斷點”, 其實現一般需要CPU支持硬件斷點,如果純軟件實現watchpoint,那好像會很耗CPU.(我沒
去看gdb的軟0watchpoint的實現,有時間得去研究下,不過如果讓我來實現這個功能(和同事討論過),應該是設置watchpoint所在的
那個頁表為不可讀/訪問,然后在缺頁處理那檢測當前的頁和地址是否是軟設置watchpoint所在的頁和watchpoint的地址,如果是,則
說明可以假設該watchpoint發生了)

目前支持watchpoint硬件斷點的arch有x86,ppc和mips。

如果支持硬件斷點,那么可以將監控的操作交給硬件來完成,而gdb這邊只要做個簡單的邏輯處理就行.
還是以上面的gdb-sample.c為例:

當gdb執行watch n命令后,gdb會在n變量所在的內存地址上下個硬件寫斷點


(gdb) watch n 
Hardware watchpoint 2: n 

(如果是 rwatch n命令,gdb會在n變量所在的內存地址上下個硬件讀斷點)
(tips: gdb 通過系統調用ptrace()去修改調試寄存器值,從而達到實現硬件斷點的目的)

這樣只要系統操作了n變量(內存地址),就會觸發一個硬件斷點中斷。
gdb捕獲到這個斷點中斷后,就會將新的n變量值和改變前的值做比較,
1)如果n變量的值改變了,則將程序停止。
2)如果n變量的值沒有改變了,則程序繼續運行。

關於硬件斷點,可以參考x86 調試寄存器 一文。

3: 遠程gdb server的watchpoint 實現

如果調試本地應用程序,gdb可以直接通過ptrace發出的信號得到watchpoint信息。

如果遠程調試程序,gdb怎么從遠程gdb server那得到watchpoint信息呢?

說到這里,又不得不搬出 GDB遠程串行協議了..
在GDB遠程串行協議里定義了gdb server和gdb所有的通信規則,所以要告訴gdb,遠程gdb server那邊踩中watchpoint了,還得通過那個協議來傳達。

在GDB遠程串行協議的Stop-Reply-Packets里定義了如何傳達watchpoint信息:

?View Code TEXT
 
`T AA n1:r1;n2:r2;...'
    The program received signal number AA (a two-digit hexadecimal number).
    This is equivalent to an `S' response, except that the `n:r' pairs can
    carry values of important registers and other information directly in
    the stop reply packet, reducing round-trip latency. Single-step and
    breakpoint traps are reported this way. Each `n:r' pair is interpreted
    as follows:
        * If n is a recognized stop reason, it describes a more specific
    event that stopped the target. The currently defined stop reasons are
    listed below. aa should be `05', the trap signal. At most one stop 
    reason should be present.
 
    The currently defined stop reasons are:
    `watch'
    `rwatch'
    `awatch'
     The packet indicates a watchpoint hit, and r is the data address, in hex.

所以只要在Stop-Reply-Packets里添加 watch+斷點地址格式的數據,gdb就知道那邊踩中watchpoint了.

3. 參考文檔

本文地址:
http://www.kgdb.info/gdb_watchpoint/
版權所有 © 轉載時必須以鏈接形式注明作者和原始出處!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM