linux内核调试,模块中使用内核未导出接口

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
内核版本:5.10

内核模块调试时候会遇到当前编译的linux内核没有导出一个函数而不能使用这个函数,比如删除文件的 do_unlinkat 函数,如何在模块中使用内核没有导出的函数呢,下面介绍下模块中使用内核没有导出的函数的方法。


提示:以下是本篇文章正文内容,下面案例可供参考

一、模块中使用内核没有导出的函数

1,查看内核函数在当前内核的地址
可以通过查看 /proc/kallsyms 节点找内核函数地址
cat /proc/kallsyms | grep do_unlinkat
在这里插入图片描述
或者内核编译完后会生成System.map文件,这个文件包含也是函数的地址,也可以使用,需要注意使用和当前系统配套的system.map
2,查看内核的这个函数定义,将这个地址转成函数指针然后使用
内核定义:
struct filename *
getname_kernel(const char * filename)

long do_unlinkat(int dfd, struct filename *name)

模块定义示例:
typedef struct filename* (getname_kernel_func_t)(char);
getname_kernel_func_t getname_kernel_ptr = (getname_kernel_func_t)0xffffffffb534f7a0;

typedef long (do_unlinkat_func_t)(int , struct filename);
do_unlinkat_func_t do_unlinkat_ptr = (do_unlinkat_func_t)0xffffffffb5351760;

内核中有函数可以通过地址或者函数名相互获取,但是通过函数名称获取地址的函数没有导出
int lookup_symbol_name(unsigned long addr, char *symname) //未导出
int sprint_symbol(char *buffer, unsigned long address)
{
return __sprint_symbol(buffer, address, 0, 1);
}
EXPORT_SYMBOL_GPL(sprint_symbol);

二、代码示例

使用代码前,需要将定义大的函数地址换成 当前电脑上的函数的内核地址(章节一有说明),否则可能出现异常

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/sysfs.h>

#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/binfmts.h>
#include <linux/kallsyms.h>

#define DEVICE_NAME "mychardev"
#define CLASS_NAME "mychardev_class"

static dev_t dev_num; // 设备号
static struct cdev my_cdev; // cdev 结构体
static struct class *my_class; // 设备类
static struct device * my_device;


#define BUFFER_SIZE 1024 // 定义缓冲区大小

ssize_t open_read_close_file(const char *path)
{
   
   
    struct file *filp;
    char *buffer;
    ssize_t bytes_read;
    int err;

    // 分配缓冲区以存储读取的数据
    buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
    if (!buffer) {
   
   
        return -ENOMEM; // 内存分配失败
    }

    // 使用 vfs_open 打开文件
    filp = filp_open(path, O_RDWR | O_CREAT, 0644);

    if (IS_ERR(filp)) {
   
   
        kfree(buffer); // 释放缓冲区
        return -1;
    }

    // 从文件读取数据
    bytes_read = kernel_read(filp, buffer, BUFFER_SIZE - 1, &filp->f_pos);
    if (bytes_read >= 0) {
   
   
        buffer[bytes_read] = '\0'; // 确保字符串结束符
        printk(KERN_INFO "Read from file: %s\n", buffer); // 打印读取的内容
    } else 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值