qemu 单步调试linux driver

本文介绍了如何在QEMU环境中单步调试ARM64Linux内核驱动,包括环境准备(如创建简单的helloworld示例),加载和调试步骤,以及使用GDB查看和设置断点。重点讨论了加载模块后的符号查找、不同调试方法和符号表的正确设置。

一、背景

qemu单步调试arm64 linux kernel-优快云博客介绍了如何单步调试kernel, 但是我们经常写一些测试driver, driver的部分如何调试?

二、环境准备

调试driver 就需要准备一个简单的driver, 这里用最简单的hello world来演示如何调试,程序非常简单,生成一个字符设备,并且在cat的时候打印变量,还加了一个全局变量,用来gdb调试查看变量使用

#include <linux/module.h>     /* Needed by all modules */
#include <linux/kernel.h>     /* Needed for KERN_INFO */
#include <linux/init.h>       /* Needed for the macros */
#include <linux/miscdevice.h> /* Needed for misc device */

int global_hello_value = 996;

#define    DEVICE_NAME     "Helloworld"

void test_for_debug(void)
{   
    printk(KERN_INFO "just for debug the text section %d", global_hello_value);
}

static int hello_open(struct inode *inode, struct file *file){
    test_for_debug();
    return 0;
}
 
static struct file_operations hello_fops = { 
    .owner  =   THIS_MODULE,
    .open   =   hello_open,     
};

static struct miscdevice hello_misc = { 
    .minor  = MISC_DYNAMIC_MINOR,
    .name   = "Helloworld",
    .fops   = &hello_fops,
};

static int __init hello_start(void) 
{
    int ret;
    ret = misc_register(&hello_misc);
    if (ret < 0) {
      printk(KERN_EMERG " %s register failed %d.\n", DEVICE_NAME, ret);
      return ret;
    }   
    printk(KERN_INFO "Hello world\n"); 
    return 0;  
}

  
static void __exit hello_end(void) 
{ 
    test_for_debug();
    misc_deregister(&hello_misc);
    printk(KERN_INFO "hello_end Goodbye\n"); 
} 

MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("geek");
MODULE_DESCRIPTION("A simple Hello world misc driver!");
MODULE_VERSION("0.1");

module_init(hello_start);
module_exit(hello_end);

编译ko需要使用 make modules指令

make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- modules -j8

编译完成后,会在hello driver的源码目录生成对应的ko文件;

将ko 放在我们的rootfs 中,参考前一篇 无人知晓:qemu搭建arm64 linux kernel调试环境 rootfs image制作部分,挂载rootfs.img, 拷贝ko, 然后umount img

sudo mount rootfs.img rootfs
sudo mkdir rootfs/driver
sudo cp ../hello_driver.ko rootfs/driver/
sudo umount rootfs

三、加载ko

insmod 加载打印hello world, 同时生成/dev/Helloworld节点

~ # insmod driver/hello_driver.ko 
[   11.203785] Hello world
~ # cd /dev/
/dev # ls
Helloworld       ptypc            tty36            ttyp0

gdb 连接后,尝试看下之前ko的global_hello_value变量,无法显示,test_for_debug函数也是无法找到的

(gdb) p global_hello_value
No symbol "global_hello_value" in current context.
(gdb) b test_for_debug
Function "test_for_debug" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n

四、调试ko

调试ko的步骤也是分三步:先加载ko, 确认ko加载的地址;然后加载ko symbols,加载地址需要和实际加载一致 ; 最后一步就是加断点,然后启动调试即可

方法1: insmod ko之后根据节点/sys/module/XXXX/sections/ 确认ko 加载的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值