http://lib.csdn.net/article/linux/40781
How about android ? :
code:
system/core/toolbox/r.c
usage:
#/system/bin/r 0x1013000
#/system/bin/r 0x1013004
#/system/bin/r 0x1013008
#/system/bin/r 0x101300C
问题
这段时间实验室要完成一个内存故障注入工具和寄存器故障注入工具,在编写驱动的过程中,调试起来很麻烦(一般都是printk打印出来的,调试起来太不方便),于是想
“可不可以在调试设备驱动的时候,利用一个小工具来读写内存某块区域的值以及CPU中寄存器的值?
这点前辈的大神已经为我们找到了,参见《LDD3》的《第十五章 内存映射和DMA》
目前已经有这样的工具了devmem和devkmem,就是通过mmap映射/dev/mem的。
这个工具的源码简单,google一下到处都是,这里随便给出一两个地址:
http://sources.buildroot.net/devmem2.c
https://dev.openwrt.org/browser/packages/utils/devmem2/src/devmem2.c
/dev/mem和/dev/kmem其实是在同一个驱动中代码中产生的:drivers/char/mem.c
如果想知道具体的情况,建议大家认真学习《LDD3》的《第十五章 内存映射和DMA》,然后自己分析源码。
Linux下/dev/mem和/dev/kmem的区别
devmem
使用
Usage: ./devmem { address } [ type [ data ] ]
address : memory address to act upon
type : access operation type : [b]yte, [h]alfword, [w]ord
data : data to be written
参数 | 描述 |
---|
address | 物理地址,如果是要修改该地址的数据,需要填入下面的参数;如果只是读取,省略即可 |
type | 要访问的数据类型 [b]yte, [h]alfword, [w]ord |
data | 想要写入的数据 |
通过使用,发现IO内存和物理内核都可以读写。
源码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
int main(int argc, char **argv) {
int fd;
void *map_base, *virt_addr;
unsigned long read_result, writeval;
off_t target;
int access_type = 'w';
if(argc < 2) {
fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
"\taddress : memory address to act upon\n"
"\ttype : access operation type : [b]yte, [h]alfword, [w]ord\n"
"\tdata : data to be written\n\n",
argv[0]);
exit(1);
}
target = strtoul(argv[1], 0, 0);
if(argc > 2)
access_type = tolower(argv[2][0]);
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
printf("/dev/mem opened.\n");
fflush(stdout);
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
if(map_base == (void *) -1) FATAL;
printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
virt_addr = map_base + (target & MAP_MASK);
switch(access_type) {
case 'b':
read_result = *((unsigned char *) virt_addr);
break;
case 'h':
read_result = *((unsigned short *) virt_addr);
break;
case 'w':
read_result = *((unsigned long *) virt_addr);
break;
default:
fprintf(stderr, "Illegal data type '%c'.\n", access_type);
exit(2);
}
printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result);
fflush(stdout);
if(argc > 3) {
writeval = strtoul(argv[3], 0, 0);
switch(access_type) {
case 'b':
*((unsigned char *) virt_addr) = writeval;
read_result = *((unsigned char *) virt_addr);
break;
case 'h':
*((unsigned short *) virt_addr) = writeval;
read_result = *((unsigned short *) virt_addr);
break;
case 'w':
*((unsigned long *) virt_addr) = writeval;
read_result = *((unsigned long *) virt_addr);
break;
}
printf("Written 0x%X; readback 0x%X\n", writeval, read_result);
fflush(stdout);
}
if(munmap(map_base, MAP_SIZE) == -1) FATAL;
close(fd);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
devkmem
在后来的模块调试中,有一次需要查看内核虚拟地址中的数据,我又想起了“/dev/kmem”,
使用
使用方法: 用 cat /proc/kallsyms | grep *** 找到要查看的变量的地址, 这个地址作为本程序的输入参数。
用法: devkmem { address }
参数 | 描述 |
---|
address | 虚拟地址(内核逻辑地址) |
源码
(仅支持读取)内核虚拟地址中的数据。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#define DEVKMEM "/dev/kmem"
#define PAGE_SIZE 0x1000
#define PAGE_MASK (~(PAGE_SIZE-1))
int main(int argc, char* argv[])
{
int fd;
char *mbase;
char read_buf[10];
unsigned int regAddr;
unsigned int varAddr;
varAddr = strtoul(argv[1], 0, 16);
unsigned int ptr = varAddr & ~(PAGE_MASK);
fd = open(DEVKMEM, O_RDONLY);
if (fd == -1) {
perror("open");
exit(-1);
}
mbase = mmap(0,PAGE_SIZE,PROT_READ,MAP_SHARED,fd, (varAddr & PAGE_MASK));
if (mbase == MAP_FAILED) {
printf("map failed %s\n",strerror(errno));
}
printf("varAddr = 0x%X \n", varAddr);
printf("mapbase = 0x%X \n", (unsigned int)mbase);
printf("value = 0x%X \n",*(unsigned int*)(mbase+ptr));
printf("char = %c%c%c%c \n",
*(char *)(mbase+ptr), *(char *)(mbase+ptr+1),
*(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3));
close(fd);
munmap(mbase,PAGE_SIZE);
return 0;
}