解决交叉编译内核模块后insmod时出现的invalid module format问题:disagrees about version of symbol module_layout

在交叉编译内核模块在目标机器进行insmod时,出现invalid module format报错,查询相关资料,这个报错主要是由于内核模块的版本信息和目标机的Linux版本不一致导致的,但是我的情况要比这个更复杂一点。

想要确认版本问题,可以使用modinfo指令查看自己的内核模块的信息,再和目标机自带的内核模块的信息进行对比,主要需要查看vermagic这部分字段:
在这里插入图片描述
这部分字段主要是由自己下载的与目标机相同版本的Linux内核代码的配置有关,关于这部分的内容我是直接找到目标机的config.gz文件复制到自己的目录下,解压后直接重命名为.config解决的,在复制后,需要重新编译,采用make oldconfig命令,会补充设置一些新的选项,然后再重新编译内核、编译内核模块,查看modinfo进行比较。
其中使用的命令可以参考:

make clean
make mrproper
make distclean
gunzip -c config.gz > .config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  -j8

最开始我的内核模块的vermagic缺少了"SMP"标识,对比目标机和本机的.config文件发现是缺少了CONFIG_SMP这几个选项。这应该是在补充设置新的选项时一些选择导致的,但是配置时也没有明确设置SMP的地方,我就多尝试了几次不同的配置方案试出来的,具体的内在逻辑也没有具体了解,后面还需要多学习。
在这里插入图片描述

但是在我把vermagic配置完全一致后,依旧报错invalid module format,所以还存在一些潜在的问题,后面我还尝试了使用modprobe命令加载内核模块。在这个过程中,我查到一些资料的解决方案是在目标机上通过以下指令查询模块加载报错信息

dmesg | grep module

如果查询module没有看到相关信息,可以试着查询自己的模块名:

dmesg | grep lkm(lkm就是我的模块名)

然后就查看到以下内容:disagrees about version of symbol module_layout

模块加载时版本校验机制相关资料:
Linux 的开发者为了保证内核的稳定,Linux 在加载模块到内核时对模块采用了版本校验机制。Linux 对可加载内核模块采取了两层验证:模块的 CRC 值校验和 vermagic 的检查。
其中模块 CRC 值校验针对模块导出符号,是一种简单的 ABI一致性检查;模块 vermagic 则保存了模块编译时的内核版本以及 SMP 等配置信息。Linux 内核在进行模块装载时先完成模块的 CRC 值校验,再核对 vermagic 中的字符信息,linux版本。
综上,disagrees about version of symbol module_layout 报错是没有通过 CRC 值校验,即 module_layout 的 CRC 值与当前内核中的不符。

module_layout可以通过以下指令进行查询:

sudo modprobe  --dump-modversions 模块位置 | grep module_layout

查看自己的内核模块和目标机自带的内核模块的module_layout信息,发现模块(lkm.ko)和目标机自带的模块(ss.ko、can.ko)的相关值不一致。
在这里插入图片描述
模块的module_layout信息也可以通过查看内核模块编译生成的.mod.c文件(以下是已经修改过crc值后的截图):
在这里插入图片描述

接下来就需要解决module_layout不一致问题。
通常,内核与模块的导出符号的 CRC 值被保存在内核所在目录下的文件 Module.symvers 中。
先转到下载的内核代码目录下:
在这里插入图片描述
具体修改代码:

#进入到 .tmp_version 目录中,重命名所有的后缀名为 .mod 的文件
cd .tmp_versions
rename 's/\.mod$/.bak/' *.mod  

#重命名 vmlinux 文件
cd ../
mv ./vmlinux vmlinux-bak

#修改 Module.symvers 文件,0x902b926b就是对目标机的module_layout值
sed -i  '/module_layout/ s/0x[0-9a-f][0-9a-f]*/0x902b926b/' Module.symvers  

然后再转到自己编写的内核模块代码目录下进行交叉编译即可,编译命令和之前的一样:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 

修改module_layout这部分具体见参考3:https://blog.csdn.net/Longyu_wlz/article/details/109546013。

以上内容是自己在交叉编译内核模块后进行部署的过程中遇到的问题以及解决方案摸索过程的简单记录,如有错误,请多多指正。

参考:

  1. https://www.cnblogs.com/sinferwu/p/12598820.html 解析 Linux 内核可装载模块的版本检查机制
  2. https://zhuanlan.zhihu.com/p/414290127 insmod内核模块报错disagrees about version of symbol XXX
  3. https://blog.csdn.net/Longyu_wlz/article/details/109546013 修改模块符号 crc 校验码并探讨 modpost 的部分工作原理
  • 43
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值