加载内核模块-Unknown symbol错误分析
Unknown symbol 说明 有些函数不知道(未定义)。
在调试过程中,发现一个问题,编译生成一个KO文件,insmod加载后报错:
Unknown symbol var_set_integer (err 0)
Unknown symbol parse_arg_eq (err 0)
问题分析思路:
一、用命令查看内核中是否已有这个内核符号,
例如要查看是否有var_set_integer这个内核符号,输入命令:
#cat /proc/kallsyms | grep "var_set_integer"
没有相关打印,而输入其它的函数名则会有打印信息。
如果内核中已经包含了这个符号,那么就会有相关的打印信息,否则不打印。
注:
/proc/kallsyms会显示内核中所有的符号,但是这些符号不是都能被其他模块引用的(绝大多数都不能),能被导出的是符号的类型是大写的那些(例如T,U)。
二、使用modinfo查看内核相关信息,确定模块依赖关系,再进一步确认符号调用。
例如:
[root@localhost sw_64-3_8]# modinfo linux-bcm-core.ko
filename: linux-bcm-core.ko
license: GPL //权限
description: BCM Core Device Driver
depends: linux-kernel-bde // 由此可看出linux-bcm-core.ko 依赖于linux-kernel-bde.ko
vermagic: 3.8.0-sw2f SMP mod_unload modversions //内核版本
三、在源码中搜索这几个函数定义的地方,看是否有使用EXPORT_SYMBOL,是否有extern声明;
并且查看是否要做GPL声明:修改为 MODULE_LICENSE("GPL");
(1)如果你的模块需要输出符号给其他模块使用, 应当使用下面的宏定义:
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);//只用于包含 GPL 许可权的模块。
符号必须在模块文件的全局部分输出, 在任何函数之外, 因为宏定义扩展成一个特殊用途的并被期望是全局存取的变量的声明. 这个变量存储于模块的一个特殊的可执行部分( 一个 "ELF 段" ), 内核用这个部分在加载时找到模块输出的变量.
(2)EXPORT_SYMBOL使用方法:
1)在模块函数定义之后使用EXPORT_SYMBOL(函数名);
2)在调用该函数的模块中使用extern对之声明;
3)首先加载定义该函数的模块,再加载调用该函数的模块。【模块加载顺序的前后要求,一般就是依赖于符号调用】
编译生成ko模块之后,用insmod命令加载此模块到内核。这个程序加载模块的代码段和数据段到内核。
接着, 连接模块中任何未解决的符号到内核的符号表上.
也就是说:
【insmod使用公共内核符号表来解析模块中未定义的符号】,公共内核符号表中包含了所有的全局内核项(即函数和变量)的地址,这是实现模块化驱动程序所必需的。
同时也可以【导出自身模块中的任何内核符号到公共内核符号表】,如图:
在通常情况下,模块只需实现自己的功能,而无需导出任何符号。但是,如果其他模块需要从某个模块中获得好处时,我们也可以导出符号。
四、在模块目录下查看Module.symvers,看是否存在要找的符号。
Module.symvers contains a list of all exported symbols from a kernel build.
Module.symvers包含所有要导出的列表符号。
Module.symvers file 的语法格式:
<CRC> <Symbol> <module>
0x2d036834 scsi_remove_host drivers/scsi/scsi_mod
当内核编译选项CONFIG_MODVERSIONS关闭时,所有的CRC值都为0x00000000。
补充:
1,
【 Linux模块间通讯方法非常的多,最便捷的方法莫过于函数符号导出,然后直接调用。】
2,
驱动也是存在于内核空间的,它的每一个函数每一个变量都会有对应的符号,这部分符号也可以称作内核符号,
它们不导出(EXPORT_SYMBOL)就只能为自身所用,导出后就可以成为公用,对于导出的那部分内核符号就是我们常说的内核符号表。
insmod的时候并不是所有的函数都得到内核符号表去寻找对应的符号,
每一个驱动在自已的分配的空间里也会存在一份符号表,里面有关于这个驱动里使用到的变量以及函数的一些符号,首先驱动会在这里面找,如果发现找不到就会去公共内核符号表中搜索,搜索到了则该模块加载成功,搜索不到则该模块加载失败。
2.6内核默认情况下,是不会在模块加载后把模块中的非静态全局变量以及非静态函数自动导出到内核符号表中的,需要显式调用宏EXPORT_SYMBOL才能导出。
对于一个模块来讲,如果仅依靠自身就可以实现自已的功能,那么可以不需要要导出任何符号,只有其他模块中需要使用到该模块提供的函数时,就必须要进行导出操作。
由此启发,因为LKM中所存取的每一个符号(像函数名)也会被列在内核符号表中,有时候我们可以看内核符表就可以看到LKM调用的那些函数,如果这个LKM为非法目的,那么我们可以杀掉这个LKM.
名词解释:【LKM:可装载模块(Loadable Kernel Module )】
参考:
http://lxr.free-electrons.com/source/Documentation/kbuild/modules.txt
http://blog.csdn.net/macrossdzh/article/details/4601648
http://secisland.blog.51cto.com/787880/319760
转自:http://blog.csdn.net/wuyongpeng0912/article/details/46739233
加载内核模块-Unknown symbol错误分析的更多相关文章
- Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块
Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...
- CentOS启动时自动加载内核模块
要想在CentOS中自动加载内核模块,需要在/etc/sysconfig/modules/目录中增加一个脚本,在此脚本中加载所需的模块. 下面是我所用的一个名为8021q.modules的脚本,用来在 ...
- 爱之初体验---编译加载内核模块hello
1. hello.c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h ...
- 内核加载模块时出现Unknown symbol等提示
一.背景 1.更改了内核的配置,重新编译了内核 2.未重新编译内核模块 3.板子上只更新了内核,并未更新文件系统 二.分析 发现是在加载内核模块时出现Unknown symbol等信息,恰逢当时只更新 ...
- insmod: can't insert 'xxx.ko': unknown symbol in module, or unknown parameter
手动加载内核模块时候,报如下错误信息 insmod: can't insert 'xxx.ko': unknown symbol in module, or unknown parameter 问题原 ...
- insmod 时报错“Unknown symbol”问题的解决
在加载驱动模块时报错: “ Unknown symbol CFG80211_SupBandReInit (err 0)” 查看了内核代码以及加载上的symbol(命令为 cat /proc/kalls ...
- linux内核裁剪及编译可加载模块
一:linux内核裁剪: 1:编译内核源码: 今天的重点内容是内核驱动的编写,在编写驱动之前首先的了解linux内核源码,linux主要是由五个子系统组成:进程调度,内存管理,文件系统,网络接口以及进 ...
- CentOS中自动加载802.1q模块
要想在CentOS中自动加载内核模块,需要在/etc/sysconfig/modules/目录中增加一个脚本,在此脚本中加载所需的模块. 下面是我所用的一个名为8021q.modules的脚本,用来在 ...
- linux内核及其模块的查询,加载,卸载 lsusb等
http://blog.sina.com.cn/s/blog_53e81e2a0100zkxi.html 1,/sbin/update-modules文件,他是一个linux通用的模块管理脚本程序. ...
随机推荐
- H.264采集、编码、传输的流程
转载自H.264采集.编码.传输的流程 1 采集到的原始数据放入buf中 2 转化为yuv格式放入yuv conv.RGB24_to_YV12(buf, yuv,IMAGE_WIDTH, IMAGE_ ...
- zookeeper数据一致性与paxos算法
数据一致性与paxos算法 据说Paxos算法的难理解与算法的知名度一样令人敬仰,所以我们先看如何保持数据的一致性,这里有个原则就是: 在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点都执 ...
- c# 数据库批量插入数据SqlBulkCopy 示例
/// <summary> /// 批量插入数据 /// </summary> public static void SqlBulkInsert(DataTable dt, s ...
- linux 下 iscsi的简单使用
一.准备工作 1.1.(服务端和客户端都需要设置) 系统使用的是CentOS6.8 禁用防火墙: 查看状态:# service iptables status 停止:# systemctl sto ...
- Android内存优化(三)避免可控的内存泄漏
相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...
- HDU 1806
http://acm.hdu.edu.cn/showproblem.php?pid=1806 非常玄妙的rmq问题,这个st算法有点神 #include <iostream> #inclu ...
- .net collection tips
1.数组对象都是Array的子类,Array是一个抽象类,不能显示实例化,Array提供了大量操作数组的静态方法 2.ArrayList其实是内部封装了一个array,实现了IList的接口.add ...
- BJOI 2019 模拟赛 #2 题解
T1 完美塔防 有一些空地,一些障碍,一些炮台,一些反射镜 障碍会挡住炮台的炮, 反射镜可以 90° 反射炮台的光线,炮台可以选择打他所在的水平一条线或者竖直一条线 求是否有一组方案满足每个空地必须要 ...
- 使用python处理selenium中的窗口切换问题
# 获取当前页面的句柄 ch = self.driver.current_window_handle # 获取所有句柄 ah = self.driver.window_handles # 切换句柄 s ...
- MySQL 导入.sql文件
对于新手,刚接触Mysql数据库不知道,怎么导入sql脚本数据库. 或者说几百M的,导入肯定会卡死,所以用命令来导入是比较好的选择, 讲下方法. 在 linux 终端下 执行 mysql -uroot ...