2010-09-03 269 views
4

我遇到了GDB和內核空間中分配的一些緩衝區的問題。緩衝區由內核模塊分配,內核模塊應該分配連續的內存塊,然後通過mmap()調用將內存映射到用戶空間。然而,GDB似乎無法隨時訪問這些塊。例如,創GDB斷點後:GDB無法訪問mmap()內核分配的內存?

(gdb) x /10xb 0x4567e000 
0x4567e000:  Cannot access memory at address 0x4567e000 

然而,看着應用程序的當前映射的內存區域在/ proc // smaps顯示:

4567e000-456d3000 rwxs 8913f000 00:0d 883  /dev/cmem 
Size:    340 kB 
Rss:     340 kB 
Pss:     0 kB 
Shared_Clean:   0 kB 
Shared_Dirty:   0 kB 
Private_Clean:   0 kB 
Private_Dirty:   0 kB 
Referenced:   0 kB 
Swap:     0 kB 

的原因,我甚至看這是因爲在運行過程中的某個時刻,這個緩衝區地址(或者以類似方式分配的另一個地址)會導致SIGSEGV。

Program received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x49aea490 (LWP 652)] 
0x402e4ea8 in fwrite() from /lib/libc.so.6 
(gdb) 
(gdb) 
(gdb) where 
#0 0x402e4ea8 in fwrite() from /lib/libc.so.6 
#1 0x000eb394 in EncryptedWriter::Write (this=0x198600, buffRaw=0x4567e000 <Address  0x4567e000 out of bounds>, iLenRaw=719) at encrypted_writer.cpp:397 
#2 0x0006b0f4 in EncryptionWrapper::Write (this=0x3ab2698, buffer=0x4567e000, size=719) at encryption.cpp:54 

該段錯誤發生,儘管該緩衝區已被大量使用,直到崩潰的事實,並在/ proc // smaps文件還表示要爲上述映射此緩衝區。

我完全不知道爲什麼會出現這種情況,爲什麼映射在/ proc中看起來有效,但從來沒有在GDB中有效。

+0

因此,你的應用程序段錯誤,而它試圖訪問此映射*和* gdb說,它無法訪問映射嗎?難道由於某種原因映射變得無法訪問,而/ proc/smaps只是不顯示這個?這是哪個內核模塊? – 2010-09-03 22:56:41

+0

是的,但GDB在segfault之前甚至無法訪問映射,就我所知,它也無法在任何時候訪問此內核模塊的任何映射。我認爲可能映射變得無法訪問,但我對內核內存管理知之甚少,不知道可能是什麼原因,以及爲什麼/ proc/smaps不能反映這種變化。分配這些模塊的模塊是德州儀器的連續存儲器(CMEM)模塊。它與CodecEngine API一起使用,用於管理目標爲不具有MMU的協處理器的緩衝區。 – 2010-09-03 23:04:30

回答

5

關於爲什麼gdb無法訪問你想要的內存,我相信Linux不會通過ptrace()訪問I/O內存。根據cmemk.c(我在linuxutils_2_25.tar.gz中找到),mmap()確實在所討論的內存中設置了VM_IO標誌。

要從gdb訪問此內存,請在程序中添加一個讀取此內存並使gdb調用此函數的函數。

+0

好的,我沒有意識到這個限制,並且cmem確實設置了VM_IO(就像/ dev/mem的驅動程序一樣,所以這很有意義)。謝謝。 任何想法爲什麼GDB會聲明地址超出堆棧幀1的邊界而不是堆棧幀2? – 2010-09-03 23:54:31

+0

這可能是你正在尋找的錯誤。 1. Wrapper()得到一個有效的指針2.另一個線程(或Wrapper(),不太可能)釋放這個指針3. Wrapper()仍然將這個指針傳遞給Writer()4. Writer()將這個指針傳遞給fwrite() 5. fwrite()使用這個指針並死掉 – sigjuice 2010-09-04 00:19:56

+0

實際上,緩衝區地址是一個全紅鯡魚。原來另一個線程正在關閉文件指針,所以fwrite因此死亡。在線程拆卸後,緩衝區本身不會被釋放,直到進程關閉。謝謝您的幫助! – 2010-09-04 02:43:48

0

請參閱examining-mmaped-addresses-using-gdb討論在另一個線程中,尤其是答案here。您應該能夠在模塊的mmap實現中爲您的VMA添加自定義vm_operations_struct

另請參閱Linux內核中的mm/memory.c。當get_user_pages()失敗時,代碼將嘗試調用驅動程序中的自定義vma->vm_ops->access實現來訪問內存。