2010-04-30 33 views
3

有時候在帶有簡單MMU的嵌入式系統上工作時,我曾經動態地編程此MMU以檢測內存損壞。用於檢測內存損壞的Linux C調試庫

例如,在運行時的某個時候,foo變量被一些意外的數據覆蓋(可能是懸掛指針或其他)。因此,我添加了額外的調試代碼:

  • 在init處,foo使用的內存被指示爲MMU的禁止區域;
  • 每次foo被故意訪問,訪問該區域之前都被禁止;
  • 添加了一個MMU irq處理程序,用於轉儲主機和負責違規的地址。

這實際上是一些觀察點,但直接由代碼本身自己處理。

現在,我想重複使用相同的技巧,但在x86平臺上。問題在於,我很難理解MMU在這個平臺上的工作方式,以及它如何被Linux使用,但是我想知道是否有任何庫/工具/系統調用已經存在來處理這個問題。

請注意,我知道存在各種工具,如Valgrind或GDB來管理內存問題,但據我所知,這些工具沒有一個是由調試代碼動態重新配置的。

我主要對Linux下的用戶空間感興趣,但也歡迎任何有關內核模式或Windows下的信息!

+0

任何在調試器中使用內存讀/寫斷點的機會?如果你知道有問題的記憶會被擊中,我就會這樣做。 – 2010-04-30 17:49:30

+0

爲什麼有一個動態可重新配置的工具很重要?如果你可以在Valgrind下啓動你的程序,並讓它給你你的流浪寫的行號,爲什麼你不想要這個? – Karmastan 2010-04-30 19:41:37

+0

@Karmastan:海報要求不要對未知內存或錯誤分配的內存進行雜散寫入,valgrind等人會捕獲的東西,但在錯誤的時間寫入完全有效的內存。 – 2010-04-30 20:07:40

回答

5

您可以使用mmap(MAP_ANONYMOUS)和mprotect函數來操作虛擬內存系統並使用相應的保護標誌。當然,你的變量需要被限制爲系統頁面大小的倍數。許多小變量會帶來很大的開銷。

當您的應用程序在管理對內存區域的訪問權限時需要正常工作。您還需要使用mmap()而不是malloc來保護受保護的區域。

這是MMU的用戶空間接口層,採用相對便攜的方式。

mmapmprotect

2

兩個很好的選擇:

  • dmalloc是取代malloc()free()有大量的調試版本,可以使用頁面邊界來檢測內存溢出/欠載,灌裝分配和圖書館釋放內存,泄漏檢查等等。
  • valgrind是一個內存調試器,它允許非常精確的內存調試(精確檢測任何超出邊界的訪問),而犧牲程序速度(程序運行速度慢得多)。它也可以做泄漏檢查。
+0

海報提到所討論的內存地址是有效的,但希望根據其他一些標準(解鎖和鎖定變量)控制變量訪問。 dmalloc不能提供這種行爲,而valgrind不能提供這種行爲。 – 2010-04-30 20:09:13

1

我認爲你能做的最好的事情就是開啓一個看門狗線程,保留一個值的副本並不斷比較其副本的工作價值。您無法準確捕捉值被覆蓋的時間,但會以您希望的任何粒度通知您。,如果您設置線程每10ms檢查一次,您將在10ms內收到通知)。

0

Electric fence是有點舊,但仍然保持和有用。許多人已經將它用作更復雜調試的起點。它非常容易修改。

我也是Valgrind的忠實粉絲,但Valgrind不適用於所有平臺。

1

mprotect()系統調用是你所追求的。這使您可以更改內存區域上的保護。

Linux下x86上的內存保護是在頁面級別完成的 - 4096字節。所以你必須安排你的受保護的變量存在於它自己的頁面上,而不是與任何其他變量共享。一種安排此方法的方法是使用posix_memalign()爲變量分配內存,使用4096作爲對齊並將大小舍入到4096的下一個倍數(實際上,您可以使用sysconf(_SC_PAGESIZE)以便攜方式確定頁面大小,而不是使用硬編碼值)。另一種方法是在聯合中分配變量,將其填充到頁面大小的倍數,並使用gcc屬性__attribute__ ((aligned (4096))來對齊變量。

代替你的MMU IRQ處理程序,您只需安裝一個信號處理器使用傳遞給sigaction()功能結構的sa_sigaction成員SIGSEGV信號。您的信號處理程序將傳遞一個siginfo_t結構作爲其第二個參數,該參數將包含具有錯誤指令地址的成員sa_addr