历史上的今天
今天是:2025年04月13日(星期日)
2018年04月13日 | ARM筆記:应用调试之自制系统调用、编写进程查看器(二)
2018-04-13 来源:eefocus
在本节里面我们就详细来讲一下如何用我们自己实现的系统调用来调试应用程序
一、步骤
1、修改应用程序的可执行文件,替换某个位置的代码为swi val
2、执行程序
3、进入到sys_hello->在sys_hello里面打印信息->执行原来的指令->返回
二、具体实现
我们的应用程序是:
//file:test_sc.c
#include
int cnt = 0;
void C(void)
{
int i = 0;
while (1)
{
printf("Hello, cnt = %d, i = %d\n", cnt, i);
cnt++;
i = i + 2;
sleep(5);
}
}
void B(void)
{
C();
}
void A(void)
{
B();
}
int main(int argc, char **argv)
{
A();
return 0;
}
具体步骤:
(1)编译:arm-linux-gcc test_sc.c -o test_sc
(2)反汇编:arm-linux-objdump -D test_sc > test_sc.dis
(3)我们打开上面得到的可执行文件和反汇编文件
比如我们想在C函数的i=i+2;处打断点的话,我们先在反汇编文件里面找到对应的指令:
84d4: e2833002 add r3, r3, #2 ; 0x2
其中:e2833002是机器码,这是我们所需要的!
我们去可执行文件里面去搜索这个机器码,在可执行文件里它对应的机器码应该是:02 30 83 e2
我们将此机器码改为swi指令的机器码!
我们可以将上一节里面的文件反汇编一下,然后得到swi的机器码为:ef900160
(4)经过上面的修改,当程序执行到i=i+2;这条指令时,会产生系统调用,最终执行sys_hello函数。
在sys_hello函数里面,我们可以最一些必要的工作,具体程序如下:
//fs/read_write.c
asmlinkage void sys_hello(const char __user * buf, int count)
{
static int cnt = 0;
int val;
int ret;
struct pt_regs *regs;
copy_from_user(&val, (const void __user *)0x000107c8, 4);
printk("sys_hello: cnt = %d\n", val);
//获取当前进程的struct pt_regs结构体,这个函数需要本文件包含一个头文件:#include
regs = task_pt_regs(current);
regs->ARM_r3 += 2;//相当于我们自己实现了那个被替换的指令
copy_from_user(&val, (const void __user *)(regs->ARM_fp - 16), 4);
printk("sys_hello: i = %d\n", val);
if (++cnt == 5)
{
copy_from_user(&val, (const void __user *)0x8504, 4);
printk("[0x8504] code = 0x%x\n", val);
printk("regs->ARM_lr = 0x%x\n", regs->ARM_lr);
val = 0xe2833002;
ret = access_process_vm(current, 0x8504, &val, 4, 1);
printk("access_process_vm ret = %d\n", ret);
cnt = 0;
}
return;
}
此外还需要在:include/linux/syscalls.h 文件里将函数声明改为:asmlinkage void sys_hello(const char __user * buf, int count);
(5)编译内核,用新内核启动
(6)运行测试程序(在此之前要修改测试程序的权限:chmod 777 test_sc_swi),输出信息如下:
Hello, cnt = 0, i = 0
sys_hello: cnt = 1
sys_hello: i = 0
Hello, cnt = 1, i = 2
sys_hello: cnt = 2
sys_hello: i = 2
Hello, cnt = 2, i = 4
sys_hello: cnt = 3
sys_hello: i = 4
测试成功!
本节讲的调试方法比较晦涩,一般不会采用!
史海拾趣
|
51单片机采用485总线通信接收来自PC机的数据,单片机程序怎么编写呀?和232的有什么不同的地方?也要初始化串口么,我想采用中断的方法接 是不是和串口232的设置一样,先要初始化串口,设置波特率,开中断等等?… 查看全部问答> |
|
各位老师好! 我在使用protues仿真时出现以下问题,无法解决,请你们帮帮忙看看是什么原因,谢谢! 在keil c 编译、连接完成后,就会出现一个提示框显示 Fail to connect command socket to port 127.0.0.1:8000 GLE=00002743 点 ...… 查看全部问答> |
|
QuartusII编译以后不能产生POF文件往往是由于没有选择EPCS器件造成,下面就如何选择EPCS介绍以下步骤: 1 打开QuartusII2 打开“Assignments/Device”3 点击“Device anf Pin Option/Configuration” 4 选择“Use Configuration device”在下拉 ...… 查看全部问答> |
|
请教一下各位,在fpga 中 从sdram 中读取图像数据时, 怎么能够做到把每一帧分别识别出来?另外,在考虑时序问题时是怎么计算的,比如 主时钟60Mhz ,大小640*480模式下。 还有就是如何根据这些计算出来的延迟周期 延迟为基准,产生不同宽度和周期的 ...… 查看全部问答> |
|
本品为工程富余的全新短距离射频传输模块,可以用做简单的家电无线控制、简单的无线数据传输、 无线遥控器,或者串口1-》无线发送-》无线接收-》串口2 模式的无线串口数据传输。主要芯片:MSP430 8位单片机CC1020 射频芯片射频PA芯片粗略参数:无线 ...… 查看全部问答> |




