寄存器调试 (2):应用层通过C代码访问(待完善)

除了前面所述通过shell命令访问寄存器外, 还支持通过C代码访问.

驱动层通过注册miscdevice设备, 实现了对应用层open/write/read等标准api的支持.

static DEVICE_ATTR(dump, 0644, misc_dump_show, misc_dump_store);
static DEVICE_ATTR(compare, 0644, misc_compare_show, misc_compare_store);
static DEVICE_ATTR(write, 0644, misc_write_show, misc_write_store);
static struct attribute *misc_attributes[] = {
    &dev_attr_dump.attr,
    &dev_attr_compare.attr,
    &dev_attr_write.attr,
    NULL
};
static struct attribute_group misc_attribute_group = {
    .name  = "rw",
    .attrs = misc_attributes
};
static struct miscdevice sunxi_reg_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = "sunxi-reg",
};

模块初始化时,通过sunxi_reg_init注册misc设备到内核, 并将属性组设为misc_attribute_group

static int __init sunxi_reg_init(void) {
    int     err;

    printk(KERN_INFO "sunxi_reg_init enter\n");
    err = misc_register(&sunxi_reg_dev);
    if(err) {
        printk(KERN_ERR "%s register sunxi debug register driver as misc device error\n", __func__);
        goto exit;
    }

    err = sysfs_create_group(&sunxi_reg_dev.this_device->kobj, &misc_attribute_group);
    if(err)
        printk("%s err: sysfs_create_group failed\n", __func__);
exit:
    return err;
}

static void __exit sunxi_reg_exit(void) {
    printk("sunxi_reg_exit enter\n");
    WARN_ON(0 != misc_deregister(&sunxi_reg_dev));
    sysfs_remove_group(&sunxi_reg_dev.this_device->kobj, &misc_attribute_group);
}

module_init(sunxi_reg_init);
module_exit(sunxi_reg_exit);

1. 获取单个寄存器的的值

按以下步骤:

(1) 打开sysfs设备节点.

fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR);

(2) 传递寄存器地址给内核.

write(fd, "0xf1c20000\n", sizeof("0xf1c20000\n"));

注意字符串请以换行符‘\n‘结尾.

(3) 将读写指针移植文件首.

lseek(fd, 0, SEEK_SET);

(4) 读取寄存器值字符串. 保存到buff.

char buf[20];

read(fd, buf, sizeof(buf));

(5) 将字符串转化成整型值

value = strtoul(buf, NULL, 16);

示例代码:

#define DUMP_TEST_STRING    "0xf1c20000\n"
int test_dump_reg(void)
{
    unsigned long value = 0;
    int     fd = 0, ret = -1;
    char     in_buf[250] = {0}, out_buf[250] = {0};

    fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR);
    if(0 == fd) {
        printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__);
        goto end;
    }
    /* store para */
    strcpy(in_buf, DUMP_TEST_STRING);
    ret = write(fd, in_buf, strlen(in_buf));
    if(ret < 0) {
        printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf);
        goto end;
    }
    printf("%s(%d): write %s success!\n", __func__, __LINE__, in_buf);
    /* seek to begin */
    if(lseek(fd, 0, SEEK_SET) < 0) {
        printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): seek to begin success!\n", __func__, __LINE__);
    /* show output value */
    ret = read(fd, out_buf, sizeof(out_buf));
    if(ret < 0) {
        printf("%s(%d): read failed, err!\n", __func__, __LINE__);
        goto end;
    }
    value = strtoul(out_buf, NULL, 16);
    printf("%s(%d): read success! out string \"%s\", value 0x%08x\n", __func__, __LINE__, out_buf, value);
    /* return success */
    ret = 0;
end:
    if(fd)
        close(fd);
    return ret;
}

运行结果打印:

2. 获取一组寄存器值

示例代码:

#define DUMP_TEST_STRING    "0xf1c20000,0xf1c20020\n"
int test_dump_reg(void)
{
    unsigned long value = 0;
    int     fd = 0, ret = -1;
    char     in_buf[250] = {0}, out_buf[250] = {0};

    fd = open("/sys/class/misc/sunxi-reg/rw/dump", O_RDWR);
    if(0 == fd) {
        printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__);
        goto end;
    }
    /* store para */
    strcpy(in_buf, DUMP_TEST_STRING);
    ret = write(fd, in_buf, strlen(in_buf));
    if(ret < 0) {
        printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf);
        goto end;
    }
    printf("%s(%d): write %s success!\n", __func__, __LINE__, in_buf);
    /* seek to begin */
    if(lseek(fd, 0, SEEK_SET) < 0) {
        printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): seek to begin success!\n", __func__, __LINE__);
    /* show output value */
    ret = read(fd, out_buf, sizeof(out_buf));
    if(ret < 0) {
        printf("%s(%d): read failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf);
    /* 这里需自行从buf中解析出需要的寄存器值 */
    ...
    //value = strtoul(out_buf, NULL, 16);
    /* return success */
    ret = 0;
end:
    if(fd)
        close(fd);
    return ret;
}

3. 写单个寄存器值

示例代码:

#define WRITE_TEST_STRING    "0x01f01018 0x000000a0\n"
int test_write_reg(void)
{
    int     fd = 0, ret = -1;
    char     in_buf[250] = {0}, out_buf[250] = {0};

    fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR);
    if(0 == fd) {
        printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__);
        goto end;
    }
    /* store para */
    strcpy(in_buf, WRITE_TEST_STRING);
    ret = write(fd, in_buf, sizeof(in_buf));
    if(ret < 0) {
        printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf);
        goto end;
    }
    printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf);
    /* seek to begin */
    if(lseek(fd, 0, SEEK_SET) < 0) {
        printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): seek to begin success!\n", __func__, __LINE__);
    /* show output value */
    ret = read(fd, out_buf, sizeof(out_buf));
    if(ret < 0) {
        printf("%s(%d): read failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf);
    /* return success */
    ret = 0;
end:
    if(fd)
        close(fd);
    return ret;
}

4. 写一组寄存器值

示例代码:

#define WRITE_TEST_STRING    "0xf1c20800 0x00000031,0xf1c20818 0x55555555\n"
int test_write_reg(void)
{
    int     fd = 0, ret = -1;
    char     in_buf[250] = {0}, out_buf[250] = {0};

    fd = open("/sys/class/misc/sunxi-reg/rw/write", O_RDWR);
    if(0 == fd) {
        printf("%s(%d): open \"%s\" failed, err!\n", __func__, __LINE__);
        goto end;
    }
    /* store para */
    strcpy(in_buf, WRITE_TEST_STRING);
    ret = write(fd, in_buf, sizeof(in_buf));
    if(ret < 0) {
        printf("%s(%d): write \"%s\" failed, err!\n", __func__, __LINE__, in_buf);
        goto end;
    }
    printf("%s(%d): write \"%s\" success!\n", __func__, __LINE__, in_buf);
    /* seek to begin */
    if(lseek(fd, 0, SEEK_SET) < 0) {
        printf("%s(%d): seek to begin failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): seek to begin success!\n", __func__, __LINE__);
    /* show output value */
    ret = read(fd, out_buf, sizeof(out_buf));
    if(ret < 0) {
        printf("%s(%d): read failed, err!\n", __func__, __LINE__);
        goto end;
    }
    printf("%s(%d): read success! out string \"%s\"\n", __func__, __LINE__, out_buf);
    /* return success */
    ret = 0;
end:
    if(fd)
        close(fd);
    return ret;
}

时间: 2024-12-14 22:00:18

寄存器调试 (2):应用层通过C代码访问(待完善)的相关文章

OD调试9—实例:深入分析代码完成软件破解

OD调试9—实例:深入分析代码完成软件破解  爆破,是最初级的解决方案,不到万不得已,我们不直接修改JNZ通关.因为这样子的话,我们就享受不到破解.逆向的真正乐趣了. 了解程序背后按照剧情发展经常会出的一些走法,逆向程序的算法,才能体会逆向的真正乐趣! 所以,今天的主题是:是男人,就跟进去吧~ 这次还是使用一个比较简单的程序,不然太复杂的话,一步步跟进程序可能会把自己搞崩溃,脑子恐怕不够搞.大家凭自己的能力,能进入多少就进入多少,一分不少,一寸不多!能力是培养出来的,耐心! 试验软件:MrBil

SparkSQL使用之JDBC代码访问Thrift JDBC Server

启动ThriftJDBCServer: cd $SPARK_HOME/sbin start-thriftserver.sh & 使用jdbc访问ThriftJDBCServer代码段: package com.luogankun.spark.sql import java.sql.DriverManager import java.sql.Connection import java.sql.PreparedStatement /** * JDBC代码访问Thrift JDBC Server *

Oracle03——游标、异常、存储过程、存储函数、触发器和Java代码访问Oracle对象

作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7476717.html 1.游标(光标)Cursor 在写java程序中有集合的概念,那么在pl/sql中也会用到多条记录,这时候我们就要用到游标,游标可以存储查询返回的多条数据. 语法: CURSOR  游标名  [ (参数名  数据类型,参数名 数据类型,...)]  IS  SELECT   语句; 例如:cursor c1 is select ename from emp; 游标

Mysql基础代码(不断完善中)

Mysql基础代码,不断完善中~ 1 //语法错误(syntax error)在语法分析阶段,源代码并未被执行,故不会有任何输出. 2 3 4 /* [命名规则] */ 5 常量名 类常量建议全大写,单词间用下划线分隔 // MIN_WIDTH 6 变量名建议用下划线方式分隔 // $var_name 7 函数名建议用驼峰命名法 // varName 8 定界符建议全大写 // <<<DING, <<<'DING' 9 文件名建议全小写和下划线.数字 // func_n

PhpStorm+xdebug远程调试Linux机器上的代码

一.背景介绍: 最近在了解网址导航项目,为了能够更加深入地了解被测对象,所以我选择了查看网址导航代码的方式进行,但是只是生硬地查看php源代码是比较生涩的,我希望能够通过IDE工具进行代码单步调试来了解整个网址导航的功能实现. 为了达成以上目的,我选择了phpstorm+xdebug来远程调试Linux上的代码.与之前白松分享的phpstorm+xdebug调试方法不同的是,前者调试的Webserver是在本地环境搭建了php+apache调试的,而我要面对的问题有: 1.网址导航的代码是部署在

使用xdebug+eclipse远程调试centOS7上的PHP代码

这两天一直在研究PHP代码的调试,原来开发一直用的var_dump,麻烦! 最近发现能使用xdebug+eclipse远程单步调试PHP,但是百度后实现此技术的文章都写得不够具体. 我照着这里零散的文章弄了2天,弄好了,把完整的过程整理一份,方便查阅. 1.首先安装xdebug,去http://xdebug.org/wizard.php将你的phpinfo()复制进去,按照提示安装. 安装完以后去配置php.ini加上下面几句话: [xdebug] xdebug.remote_enable =

转 c#代码访问https服务器以及https的webservice

最近公司做到WebService项目,但是要通过Https调用,自己在网上搜了半天,终于实现了服务端的Https,但是一直没有找到客户端如何实现,今天终于看到这篇文章,随手记录下来. 具体代码如下: 访问https的web public static void ProcessRequest() { //类似浏览器确认证书合法方法的绑定 ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValida

asp.net mvc 之旅—— 第四站 学会用Reflector调试我们的MVC框架代码

我们知道,现在能调试.net程序通常有两个,第一个是ILSpy,还是一个是Reflector,这两个小反编译软件算是我们研究底层代码中所拥有的一把 锋利小尖刀~~~,比如你看到的ILSpy这样的界面图: 但是呢!!! 用过ILSpy的同学大概都知道,这个毛软件是调试不了web代码的...也只能调试调试带有pdb符号的console之类的程序...悲剧吧!!! 但是白骨精的我们要学好mvc怎么能调试不了web代码呢?这可绝对不行...办法总是会有的. 一:下载Reflector VS 插件 那怎么

SylixOS 调试方法详解——静态代码分析

1. SylixOS调试方法介绍 SylixOS 实现了一个功能强大的调试 stub,可在设备或模拟器上在线调试应用程序,RealEvo-IDE 也提供配套的调试插件.目前 RealEvo-IDE 既支持自动推送调试.也支持传统的手动启动 gdbserver 的调试方式.在官方公布的使用手册中没有详细写出在日常开发中非常实用的几种调试方式,我们通过新建几个App工程来做相应的演示,主要有代码静态分析.代码覆盖率检查.性能分析以及一个实战案列的演示,本文主要介绍代码静态分析调试. 2. Sylix