8
votes

I'm running into an issue with GDB and some buffers allocated in kernel space. The buffers are allocated by a kernel module that is supposed to allocate contiguous blocks of memory, and then memory mapped into userspace via a mmap() call. GDB, however, can't seem to access these blocks at any time. For example, after hitting a breakpoint in GDB:

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

However, looking at the application's currently mapped memory regions in /proc//smaps shows:

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

The reason I'm even looking into this is because at some point during the run, this buffer address (or another allocated in a similar manner) causes a 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

This segfault occurs despite the fact that the buffer had been used heavily up until the crash, and the /proc//smaps file still shows this buffer to be mapped as above.

I am completely at a loss as to why this might be happening, and why the mapping seems valid in /proc but never in GDB.

2
So your app segfaults while it tries to access this mapping and gdb says that it can't access the mapping either? Could it be that the mapping became inaccessible for some reason and /proc/smaps just doesn't display this? Which kernel module is this?Uli Schlachter
Yes, but GDB can't access the mapping even before the segfault, nor can it access any mapping from this kernel module at any time, as far as I can tell. I assume it could be possible that the mapping became inaccessible, but I am not savvy enough with kernel memory management to know for what reasons that might be, and why /proc/smaps wouldn't reflect the change. The module allocating these blocks is the Contiguous Memory (CMEM) module from Texas Instruments. It's used in conjunction with their CodecEngine API for managing buffers destined for a coprocessor that has no MMU.Ryan Talbot

2 Answers

7
votes

About why gdb cannot access the memory you want, I believe Linux does not make I/O memory accessible via ptrace().

According to cmemk.c (which I found in linuxutils_2_25.tar.gz), mmap() does indeed set the VM_IO flag on the memory in question.

To access this memory from gdb, add a function to your program that reads this memory and have gdb call this function.

2
votes

See examining-mmaped-addresses-using-gdb discussion in another thread and especially the answer here. You should be able to add a custom vm_operations_struct to your VMA in the module's mmap implementation.

Also see mm/memory.c in the Linux kernel. When get_user_pages() fails the code will try to call the custom vma->vm_ops->access implementation in your driver to access the memory.