insmod *.ko : version magic '2.6.27 mod_unload ARMv6 ' should be '2.6.27-svn53 mo

来源:互联网 发布:淘宝图片美化好处 编辑:程序博客网 时间:2024/04/30 10:13

在開發kernel driver時,總是會遇到討人厭的vermagic檢查,只要目前在run的kernel版本跟driver編譯時用的kernel版本不一致,就沒辦法insmod。

bash-3.2# insmod sdio.ko

sdio: version magic '2.6.28-271-gec75a15 preempt mod_unload modversions ARMv7 '

should be '2.6.28 preempt mod_unload ARMv7 '

insmod: init_module 'sdio.ko' failed (Exec format error)

這大大降低了開發速度,尤其是當你拿不到客戶在用的kernel時,又要開發driver給他用,真的是很麻煩……

那麼要怎麼利用噁心的方式繞過去呢???

一、先把 Moudle version 檢查關掉。

user@host # ARCH=arm make menuconfig

--- Enable loadable module support                                             │ │

│ │         [ ]   Forced module loading                                      │ │

│ │         [*]   Module unloading                                           │ │

│ │         [*]     Forced module unloading                                  │ │

│ │         [ ]   Module versioning support                                  │ │

│ │         [ ]   Source checksum for all modules

二、 使用modinfo時,可以看到目前這driver的vermagic

filename: external_drivers/omap3530/Linux/sdio/sdio.ko
author: Texas Instruments Inc
alias: TIWLAN_SDIO
license: GPL
description: TI WLAN SDIO driver
depends:
vermagic: 2.6.28-271-gec75a15 preempt mod_unload ARMv7
parm: g_sdio_debug_level:debug level (int)

三、 修改 kernel 的 vermagic,再重新編譯driver

vermagic 的第一個值 2.6.28-noneed 是由這 include/linux/utsrelease.h裡的 UTS_RELEASE 所定義。

#define UTS_RELEASE "2.6.28-271-gec75a15"

之後再由 include/linux/vermagic.h 裡的 macro
去組合出 VERMAGIC_STRING , 也就是 kernel 的vermagic。

#include
#include


#ifdef CONFIG_SMP
#define MODULE_VERMAGIC_SMP "SMP "
#else
#define MODULE_VERMAGIC_SMP ""
#endif
#ifdef CONFIG_PREEMPT
#define MODULE_VERMAGIC_PREEMPT "preempt "
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif完成編譯後,你就可以得
#ifdef CONFIG_MODULE_UNLOAD
#define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload "
#else
#define MODULE_VERMAGIC_MODULE_UNLOAD ""
#endif
#ifndef CONFIG_MODVERSIONS
#define MODULE_VERMAGIC_MODVERSIONS "modversions "
#else
#define MODULE_VERMAGIC_MODVERSIONS ""
#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif

#define VERMAGIC_STRING \
UTS_RELEASE " " \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
MODULE_ARCH_VERMAGIC

所以, 我們只要把 UTS_RELEASE 改成我們的數字即可,當然若是懶得去try組合後的字串,也可以直接將VERMAGIC_STRING改成你要的字串

建議修改完 vermagic.h, utsrelease.h後,還是把kernel重編完再編kernel,比較保險。

以下是修改後,用modinfo看的結果

filename: external_drivers/omap3530/Linux/sdio/sdio.ko
author: Texas Instruments Inc
alias: TIWLAN_SDIO
license: GPL
description: TI WLAN SDIO driver
depends:
vermagic: 2.6.28 preempt mod_unload ARMv7
parm: g_sdio_debug_level:debug level (int)

------------------------------------------------------------------------------------------

 另外若你是用git 做版本控制 , 那就會出現git的版本號在kernel 編號上
 所以要把他關掉
 
 
General setup  --->
 [ ] Automatically append version information to the version strin

解釋;
CONFIG_LOCALVERSION_AUTO:                                                   │ 
  │                                                                         │ 
  │ This will try to automatically determine if the current tree is a       │ 
  │ release tree by looking for git tags that belong to the current         │ 
  │ top of tree revision.                                                   │ 
  │                                                                         │ 
  │ A string of the format -gxxxxxxxx will be added to the localversion     │ 
  │ if a git-based tree is found.  The string generated by this will be     │ 
  │ appended after any matching localversion* files, and after the value    │ 
  │ set in CONFIG_LOCALVERSION.                                             │ 
  │                                                                         │ 
  │ (The actual string used here is the first eight characters produced     │ 
  │ by running the command:                                                 │ 
  │                                                                 
  │ which is done within the script "scripts/setlocalversion".)             │ 
  │                                                                         │ 
  │ Symbol: LOCALVERSION_AUTO [=y]                                          │ 
  │ Prompt: Automatically append version information to the version string  │ 
  │   Defined at init/Kconfig:84                                            │ 
  │   Location:                                                             │ 
  │ ingT


http://blog.csdn.net/soso90soso/article/details/21603775


---------------------------------------------------------------------------------------------------------------------------------------------------------

另一篇

http://blog.sina.com.cn/s/blog_6e5e78bf010105jj.html

移植rt3070的AP驱动到装有fedora14的PC机上时,模块编译完毕后,加载时提示invalid module format。

PC机环境介绍:
内核版本:2.6.35.6-45.fc14.i686
命令行输入dmesg查看最后的日志,发现如下错误记录:
rtutil3070ap:version magic '2.6.35.14-96.fc14.i686 SMP mod_unload 686 ' should be '2.6.35.6-45.fc14.i686 SMP mod_unload 686'
其余几个模块也是同样错误

version magic真的是个很恶心的东西。。
既然提示出错了就去找原因。
查证AP驱动的makefile里内核目录变量指向的是当前PC机所用内核目录。/lib/modules/`uname -r`/build
这一步没有错。那么说明驱动的makefile是正确的
切换到/lib/modules/`uname -r`/目录下,查看build(build在此处是一个符号链接), ls -al 发现build指向的目录是/usr/src/kernels/2.6.35.14-96.fc14.i686,问题在这里,虽然我用的目录是/lib/modules/`uname -r`/build 这个目录貌似与我当前内核版本(uname -r 即2.6.35.6-45.fc14.i686)一致,但是build这个符号链接指向的内核源码却是2.6.35.14-96.fc14.i686的,这样造成了编译出来的模块所带的version magic是2.6.35.14-96.fc14.i686这一版本,加载时与uname -r不符。

那么要解决这一问题,就需要“篡改”一下内核源码里的version magic 。
驱动模块的version magic信息是怎么生成的:
2.6 内核下,在linux/vermagic.h中定义有VERMAGIC_STRING,VERMAGIC_STRING不仅包含内核版本号,还包含有内核 使用的gcc版本,SMP与PREEMPT等配置信息。模块在编译时,我们可以看到屏幕上会显示"MODPOST"。在此阶段, VERMAGIC_STRING会添加到模块的modinfo段。在内核源码目录下scripts\mod\modpost.c文件中可以看到模块后续处 理部分的代码。模块编译生成后,通过`modinfo mymodule.ko`命令可以查看此模块的vermagic等信息。2.6 内核下的模块装载器里保存有内核的版本信息,在装载模块时,装载器会比较所保存的内核vermagic与此模块的modinfo段里保存的 vermagic信息是否一致,两者一致时,模块才能被装载。譬如Fedora core 4 与core 2 使用的都是2.6 版本内核,在Fedore Core 2下去加载Fedora Core4下编译生成的hello.ko,会出现"invalid module format" 错误。
http://www.ibm.com/developerworks/cn/linux/l-module26/
既然是这个道理,那么只需要把/usr/src/kernels/2.6.35.14-96.fc14.i686/目录下源码中的include/linux/vermagic.h中的VERMAGIC_STRING修改成与当前PC内核uname -r一致即可。
修改如下:
#define VERMAGIC_STRING                 \
"2.6.35.6-45.fc14.i686" ""      \
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT  \
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
MODULE_ARCH_VERMAGIC
(描红为修改处)
具体的格式可以在modinfo yourmodule.ko查看之后 再确定修改哪里 修改完后重新make即可 加载后没有version magic报错提示。

0 0