使用 GDB 检查映射地址
我正在使用我在 Linux 中的直接内存访问 发布的驱动程序来映射一些物理内存到用户空间地址。 但是,我无法使用 GDB 查看任何地址; 即,x 0x12345678(其中 0x12345678 是 mmap 的返回值)失败并出现错误“无法访问地址 0x12345678 处的内存”。
有什么办法告诉GDB这块内存可以查看吗? 或者,我可以在 mmap 中做一些不同的事情(其中 foo_mmap 的调用或实现),以允许它访问此内存吗?
请注意,我不是在询问 /dev/mem (如第一个片段中所示),而是在询问通过 ioremap()、virt_to_phys() 和 remap_pfn_range() 获取的到内存的 mmap
I'm using the driver I posted at Direct Memory Access in Linux to mmap some physical ram into a userspace address. However, I can't use GDB to look at any of the address; i.e., x 0x12345678 (where 0x12345678 is the return value of mmap) fails with an error "Cannot access memory at address 0x12345678".
Is there any way to tell GDB that this memory can be viewed? Alternatively, is there something different I can do in the mmap (either the call or the implementation of foo_mmap there) that will allow it to access this memory?
Note that I'm not asking about /dev/mem (as in the first snippet there) but about a mmap to memory acquired via ioremap(), virt_to_phys() and remap_pfn_range()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我相信 Linux 不会通过 ptrace() 访问 I/O 内存。 您可以编写一个函数来简单地读取 mmap 的地址并让 gdb 调用它。 这是 foo-user.c 程序的稍微修改版本以及 gdb 会话的输出。
I believe Linux does not make I/O memory accessible via ptrace(). You could write a function that simply reads the mmap'ed address and have gdb invoke it. Here's a slightly modified version of your foo-user.c program along with the output from a gdb session.
我有你的难题的答案:)我在网上到处搜索,没有太多帮助,最后自己调试了它。
这篇文章对我来说是一个很好的起点。 我想实现类似的目标,我使用 MMAP 实现了一个字符驱动程序,将我的自定义托管内存映射到用户空间进程。 使用 GDB 时,ptrace PEEK 调用 access_process_vm() 来访问 VMA 中的任何内存。 这会导致 EIO 错误,因为通用访问无法获取内存的 PA。 事实证明,您必须通过实现 VMA 的 vm_operations_struct 的 .access 来实现该内存的访问函数。 下面是一个例子:
I have the answer to your conundrum :) I've searched everywhere online without much help and finally debugged it myself.
This post was a good starting point for me. I wanted to achieve something in similar lines, I had implemented a char driver with MMAP to map my custom managed memory to a userspace process. When using GDB, ptrace PEEK calls access_process_vm() to access any memory in your VMA. This causes a EIO error since the generic access cannot get the PA of your memory. It turns out, you have to implement an access function for this memory by implementing .access of your VMA's vm_operations_struct. Below is an example:
为了访问映射内存,GDB 将调用 ptrace,然后调用 __access_remote_vm() 来访问映射内存。 如果内存映射有 VMIO | 等标志 VM_PFNMAP(例如,remap_pfn_range()设置它们),GDB将通过用户定义的vm访问方法来访问内存。
内核已经提供了一个名为 generic_access_phys() 的通用版本,而不是编写我们自己的 access() 实现,并且可以像 /dev/mem 设备一样通过 vm_operations_struct 轻松链接此方法:
To access the mmapped memory, GDB will call ptrace, which will then call __access_remote_vm() to access the mmapped memory. If the memory is mapped with flags such as VMIO | VM_PFNMAP (for example, remap_pfn_range() sets them), GDB will access the memory though vm's access method defined by users.
Instead of writing our own implementation for access(), kernel already provides a generic version called generic_access_phys(), and this method could be easily linked via vm_operations_struct as the /dev/mem device did:
据我了解,GDB 将使用 ptrace 来探索您的进程记忆。 也许您应该编写一个简单的程序,仅附加到您的进程并使用 ptrace 从该内存中读取数据。 这可能有助于缩小根本问题的范围。 如果没有问题,那么您就知道要么我错了:),要么 GDB 发生了其他可疑的事情。
It is my understanding that GDB will be using ptrace to poke around in your process's memory. Perhaps you should write a simple program that just attaches to your process and uses
ptrace
to read from that memory. This might help narrow down what the underlying problem is. If that has no issues, then you know either I'm wrong :), or something else fishy is happening with GDB.如果
失败,您可以使用“mem”来配置内存范围。
you go "info files"
Failing this, you can use "mem" to configure memory ranges.
我认为,如果 GDB 无法访问该内存,那么它就不会映射到您的进程地址空间,因此您会得到“无法访问地址 0x12345678 处的内存”。 如果该应用程序正常运行,您将遇到分段错误。 另外,也许你的驱动程序被搞砸了,你应该检查你是否真的可以从内核内部访问内存。 尝试在这里举例:
I think that if that memory is not accessible by GDB then it is not mapped into your process address space and so you get "Cannot access memory at addresss 0x12345678". If that application were run normally you would get a segmentation fault. Also, maybe your driver is screwed and you should check you actually can access the memory from within the kernel. Try with example here:
如果打开 AF_PACKET 套接字并将其映射,gdb 将无法访问该内存。 所以你的驱动没有问题。 要么是 ptrace 的问题,要么是 gdb 的问题。
If you open an AF_PACKET socket and mmap it, gdb can't access this memory. So there isn't a problem with your driver. It's either a problem with ptrace or with gdb.