我正在使用我在Linux中的Direct Memory Access上发布的驱动程序将一些物理ram映射到用户空间地址.但是,我无法使用GDB来查看任何地址; 即,x 0x12345678(其中0x12345678是mmap的返回值)失败,并显示错误"无法访问地址0x12345678处的内存".
有没有办法告诉GDB可以查看这个内存?或者,我在mmap中可以做些什么(在foo_mmap的调用或实现),它将允许它访问这个内存?
请注意,我不是在询问/ dev/mem(如在那里的第一个片段中),而是关于通过ioremap(),virt_to_phys()和remap_pfn_range()获取的内存的mmap
我相信Linux不会通过ptrace()访问I/O内存.您可以编写一个只读取mmap的地址并让gdb调用它的函数.这是foo-user.c程序的略微修改版本以及gdb会话的输出.
#include#include #include #include #include char *mptr; char peek(int offset) { return mptr[offset]; } int main(void) { int fd; fd = open("/dev/foo", O_RDWR | O_SYNC); if (fd == -1) { printf("open error...\n"); return 1; } mptr = mmap(0, 1 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 4096); printf("On start, mptr points to 0x%lX.\n", (unsigned long) mptr); printf("mptr points to 0x%lX. *mptr = 0x%X\n", (unsigned long) mptr, *mptr); mptr[0] = 'a'; mptr[1] = 'b'; printf("mptr points to 0x%lX. *mptr = 0x%X\n", (unsigned long) mptr, *mptr); close(fd); return 0; } $ make foo-user CFLAGS=-g $ gdb -q foo-user (gdb) break 27 Breakpoint 1 at 0x804855f: file foo-user.c, line 27. (gdb) run Starting program: /home/me/foo/foo-user On start, mptr points to 0xB7E1E000. mptr points to 0xB7E1E000. *mptr = 0x61 Breakpoint 1, main () at foo-user.c:27 27 mptr[0] = 'a'; (gdb) n 28 mptr[1] = 'b'; (gdb) print peek(0) $1 = 97 'a' (gdb) print peek(1) $2 = 98 'b'
我有你的难题的答案:)我在网上搜索没有太多的帮助,最后自己调试.
这篇文章对我来说是一个很好的起点.我想用类似的方式实现一些东西,我用MMAP实现了一个char驱动程序,将我的自定义托管内存映射到用户空间进程.使用GDB时,ptrace PEEK调用access_process_vm()来访问VMA中的任何内存.这会导致EIO错误,因为通用访问无法获取内存的PA.事实证明,您必须通过实现VMA的vm_operations_struct的.access来实现此内存的访问功能.以下是一个例子:
//Below code needs to be implemented by your driver: static struct vm_operations_struct custom_vm_ops = { .access = custom_vma_access, }; static inline int custom_vma_access(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write) { return custom_generic_access_phys(vma, addr, buf, len, write); } static int custom_generic_access_phys(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write) { void __iomem *maddr; //int offset = (addr & (PAGE_SIZE-1)) - vma->vm_start; int offset = (addr) - vma->vm_start; maddr = phys_to_virt(__pa(custom_mem_VA)); if (write) memcpy_toio(maddr + offset, buf, len); else memcpy_fromio(buf, maddr + offset, len); return len; }