内核调试之devmem直接读写寄存器

简介: 内核调试之devmem直接读写寄存器

今天分享一个内核调试实用工具——devmem。

相信很多做底层驱动的人都会经常用到。

什么是devmem?

在Linux系统,如果我们想要访问某个寄存器,就需要写一个驱动程序,在驱动中映射寄存器地址,转为虚拟地址后就可以访问。

但有时候,我们只是单纯想知道某个寄存器的值,不想这么麻烦,怎么办呢?

Linux早就想到这一点了,于是提供了一个工具devmem,通过devmem就可以直接读写寄存器,

devmem是一个命令,在shell中输入devmem命令就可以非常方便的读写寄存器。

如何使用devmem?

devmem命令格式:

Usage: devmem ADDRESS [WIDTH [VALUE]]
Read/write from physical address
 ADDRESS Address to act upon
 WIDTH Width (8/16/...)
 VALUE Data to be written

ADDRESS:物理地址

WIDTH:位宽,32位、64位等等

VALUE:要写入的值

例如,读取32位寄存器0x40200000的值:

devmem 0x40200000 32

向32位寄存器0x40200000写入0x12345678

devmem 0x40200000 32 0x12345678

可以看到,devmem的使用非常简单,有了devmem就可以轻松访问寄存器。

内核配置devmem

devmem命令依赖于/dev/mem设备节点,需要在Linux内核中打开/dev/mem的配置:

Device Drivers  --->
   Character devices  --->
      [*] /dev/mem virtual device support

Linux应用层操作寄存器

除了直接使用devmem,我们也可以在Linux应用层自己实现一个devmem。

devmem的实现原理,就是打开/dev/mem,然后通过mmap映射物理地址,从而实现读写寄存器。因此,我们只要实现这些操作,就可以自己实现类似devmem的功能。

例如,在Linux应用层读取物理地址为0x40000000的值:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define MAP_SIZE 0x80000
#define base 0x40000000
int main(int argc, char **argv)
{
 int fd = open("/dev/mem",O_RDWR|O_NDELAY);
    if (fd < 0)
    {
        printf("open /dev/mem error!\n");
        return -1;
 }
    void *map_base = mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,base);
    if (map_base == MAP_FAILED)
    return -1;
    printf("%x \n",*(volatile unsigned int*)(map_base));
    close(fd);
    munmap(map_base,MAP_SIZE);
 return 0;
}

总结

devmem是一个很常用的工具,主要给驱动开发人员在Linux应用层调试使用。devmem不仅仅是访问寄存器,只要有权限访问某个物理地址,就可以使用devmem,方便我们调试。

相关文章
|
4月前
|
存储 程序员
【汇编】内存的读写与地址空间、寄存器及数据存储
【汇编】内存的读写与地址空间、寄存器及数据存储
158 1
【汇编】内存的读写与地址空间、寄存器及数据存储
|
5月前
|
存储 安全 数据安全/隐私保护
3.2 Windows驱动开发:内核CR3切换读写内存
CR3是一种控制寄存器,它是CPU中的一个专用寄存器,用于存储当前进程的页目录表的物理地址。在x86体系结构中,虚拟地址的翻译过程需要借助页表来完成。页表是由页目录表和页表组成的,页目录表存储了页表的物理地址,而页表存储了实际的物理页框地址。因此,页目录表的物理地址是虚拟地址翻译的关键之一。在操作系统中,每个进程都有自己的地址空间,地址空间中包含了进程的代码、数据和堆栈等信息。为了实现进程间的隔离和保护,操作系统会为每个进程分配独立的地址空间。在这个过程中,操作系统会将每个进程的页目录表的物理地址存储在它自己的CR3寄存器中。当进程切换时,操作系统会修改CR3寄存器的值,从而让CPU使用新的页
58 0
3.2 Windows驱动开发:内核CR3切换读写内存
|
10月前
|
Linux
Linux驱动操作地址(寄存器)的一些方式
Linux驱动操作地址(寄存器)的一些方式
112 0
|
11月前
|
存储 索引 Windows
驱动开发:内核物理内存寻址读写
在某些时候我们需要读写的进程可能存在虚拟内存保护机制,在该机制下用户的`CR3`以及`MDL`读写将直接失效,从而导致无法读取到正确的数据,本章我们将继续研究如何实现物理级别的寻址读写。首先,驱动中的物理页读写是指在驱动中直接读写物理内存页(而不是虚拟内存页)。这种方式的优点是它能够更快地访问内存,因为它避免了虚拟内存管理的开销,通过直接读写物理内存,驱动程序可以绕过虚拟内存的保护机制,获得对系统中内存的更高级别的访问权限。
6972 1
|
11月前
|
存储
驱动开发:内核读写内存多级偏移
让我们继续在`《内核读写内存浮点数》`的基础之上做一个简单的延申,如何实现多级偏移读写,其实很简单,读写函数无需改变,只是在读写之前提前做好计算工作,以此来得到一个内存偏移值,并通过调用内存写入原函数实现写出数据的目的。以读取偏移内存为例,如下代码同样来源于本人的`LyMemory`读写驱动项目,其中核心函数为`WIN10_ReadDeviationIntMemory()`该函数的主要作用是通过用户传入的基地址与偏移值,动态计算出当前的动态地址。
85 0
|
12月前
驱动开发:内核读写内存浮点数
如前所述,在前几章内容中笔者简单介绍了`内存读写`的基本实现方式,这其中包括了`CR3切换`读写,`MDL映射`读写,`内存拷贝`读写,本章将在如前所述的读写函数进一步封装,并以此来实现驱动读写内存浮点数的目的。内存`浮点数`的读写依赖于`读写内存字节`的实现,因为浮点数本质上也可以看作是一个字节集,对于`单精度浮点数`来说这个字节集列表是4字节,而对于`双精度浮点数`,此列表长度则为8字节。
219 0
|
SoC C语言
内核笔记](五)——devmem读写寄存器调试
内核笔记](五)——devmem读写寄存器调试
1061 0
驱动开发:内核CR3切换读写内存
首先CR3是什么,CR3是一个寄存器,该寄存器内保存有页目录表物理地址(PDBR地址),其实CR3内部存放的就是页目录表的内存基地址,运用CR3切换可实现对特定进程内存地址的强制读写操作,此类读写属于有痕读写,多数驱动保护都会将这个地址改为无效,此时CR3读写就失效了,当然如果能找到CR3的正确地址,此方式也是靠谱的一种读写机制。
468 0
驱动开发:内核CR3切换读写内存
|
关系型数据库 Windows
驱动开发:内核读取SSDT表基址
在前面的章节`《X86驱动:挂接SSDT内核钩子》`我们通过代码的方式直接读取 `KeServiceDescriptorTable` 这个被导出的表结构从而可以直接读取到SSDT表的基址,而在Win64系统中 `KeServiceDescriptorTable` 这个表并没有被导出,所以我们必须手动搜索到它的地址。
238 0
驱动开发:内核读取SSDT表基址
|
存储 算法 前端开发
STM32寄存器版的基础知识—内存映射
STM32F429 采用的是 Cortex-M4 内核,内核即 CPU,由 ARM公司设计。ARM 公司并不生产芯片,而是出售其芯片技术授权。芯片生产厂商(SOC)如 ST、TI、Freescale,负责在内核之外设计部件并生产整个芯片,这些内核之外的部件被称为核外外设或片上外设。如 GPIO、USART(串口)、I2C、SPI等都叫做片上外设。
252 0
STM32寄存器版的基础知识—内存映射