当前位置:  开发笔记 > 运维 > 正文

使用GDB检查mmaped地址

如何解决《使用GDB检查mmaped地址》经验,为你挑选了2个好方法。

我正在使用我在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



1> sigjuice..:

我相信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'



2> 小智..:

我有你的难题的答案:)我在网上搜索没有太多的帮助,最后自己调试.

这篇文章对我来说是一个很好的起点.我想用类似的方式实现一些东西,我用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;
}

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有