xv6(riscv)上實現kprobe

SL7發表於2022-05-01

kprobe的Linux實現原理

Linux要使用kprobe一種是有兩種方法,一是模組(Module)掛載到核心上就像掛載驅動一樣,二是透過debugfs。

Linux裡面kprobe的實現比較完善,而且要在一個大系統裡執行好各種判斷都要滴水不漏,考慮的情況相當多。但是如果簡單來講kprobe的實現就包含下面幾步:

1)註冊初始化kprobe。每個kprobe對應一個kprobe結構體,該結構中記錄著插入點(就是編譯後的核心的特定位置),以及該插入點本來對應的指令original_opcode。

2)替換原有指令。用kprobe的時候,將插入點位置的指令替換為一條異常(BRK)指令(x86 int3,riscv ebreak),讓CPU執行到插入點時產生異常,進入核心函式kprobe_int3_handler。

3)異常處理函式中執行pre_handler,然後利用CPU提供的單步除錯(single-step),設定好相應的暫存器,同時異常返回的地址改為原來的origin_opcode。

4)setup_singlestep()執行完後,繼續執行被儲存的探測點的指令,因為開啟了單步除錯某事,執行後再次觸發異常但這次是debug。

5)將single-step 清除,執行post_handler,然後從異常態安全返回。

它的一個基本思路就是將本來執行一條指令擴充套件成執行kprobe->pre_handler ---> 指令 ---> kprobe-->post_hander。

xv6上實現的設想和問題

就相當於實現一個gdb功能內嵌的函式,老實說覺得沒有比gdb除錯強多少……

  1. user態肯定傳的是要定位的某個函式名,怎麼找到特定的函式?objdump或者nm拿到函式的地址,就相當於手寫實現一個addr2line的功能。

  2. 主要是怎麼把對應地址的指令進行替換成ebreak,透過中斷的方式去跟蹤函式/指令的前後,先讓它陷入中斷執行一條命令後就返回吧。



相關文章