"no symbol version for xxx"在2.6.26内核上的问题

主要是2.6.26内核的module.c中check_version()发生了改变,在检查不到符号版本的时候返回0或者是-ENOEXEC,而之前的版本是返回1,导致的这个问题

2.6.26:代码如下:



#ifdef CONFIG_MODVERSIONS
static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod, 
                         const unsigned long *crc)
{
        unsigned int i, num_versions;
        struct modversion_info *versions;

        /* Exporting module didn't supply crcs?  OK, we're already tainted. */
        if (!crc)
                return 1;

        /* No versions at all?  modprobe --force does this. */
        if (versindex == 0)
                return try_to_force_load(mod, symname) == 0;

        versions = (void *) sechdrs[versindex].sh_addr;
        num_versions = sechdrs[versindex].sh_size
                / sizeof(struct modversion_info);

        for (i = 0; i < num_versions; i++) {
                if (strcmp(versions[i].name, symname) != 0)
                        continue;

                if (versions[i].crc == *crc)
                        return 1;
                DEBUGP("Found checksum %lX vs module %lX\n",
                       *crc, versions[i].crc);
                goto bad_version;
        }

        printk(KERN_WARNING "%s: no symbol version for %s\n",
               mod->name, symname);
        return 0;

bad_version:
        printk("%s: disagrees about version of symbol %s\n",
               mod->name, symname);
        return 0;
}

static int try_to_force_load(struct module *mod, const char *symname)
{
#ifdef CONFIG_MODULE_FORCE_LOAD
        if (!(tainted & TAINT_FORCED_MODULE))
                printk("%s: no version for \"%s\" found: kernel tainted.\n",
                       mod->name, symname);
        add_taint_module(mod, TAINT_FORCED_MODULE);
        return 0;
#else
        return -ENOEXEC;
#endif
}

2.6.25:
#ifdef CONFIG_MODVERSIONS                                                     
static int check_version(Elf_Shdr *sechdrs,                                  
                         unsigned int versindex,                             
                         const char *symname,                                
                         struct module *mod,                                 
                         const unsigned long *crc)                           
{                                                                            
        unsigned int i, num_versions;                                        
        struct modversion_info *versions;                                    
                                                                             
        /* Exporting module didn't supply crcs?  OK, we're already tainted. */
        if (!crc)                                                            
                return 1;                                                    
                                                                             
        versions = (void *) sechdrs[versindex].sh_addr;                      
        num_versions = sechdrs[versindex].sh_size                            
                / sizeof(struct modversion_info);                            
                                                                             
        for (i = 0; i < num_versions; i++) {                                 
                if (strcmp(versions[i].name, symname) != 0)                  
                        continue;                                            
                                                                             
                if (versions[i].crc == *crc)                                 
                        return 1;                                            
                printk("%s: disagrees about version of symbol %s\n",         
                       mod->name, symname);                                  
                DEBUGP("Found checksum %lX vs module %lX\n",                 
                       *crc, versions[i].crc);                               
                return 0;                                                    
        }                                                                    
        /* Not in module's version table.  OK, but that taints the kernel. */ 
        if (!(tainted & TAINT_FORCED_MODULE))                                
                printk("%s: no version for \"%s\" found: kernel tainted.\n", 
                       mod->name, symname);                                  
        add_taint_module(mod, TAINT_FORCED_MODULE);                          
        return 1;                                                            
}                      




解决方法:
1、重新编译内核,关闭CONFIG_MODVERSIONS选项
2、重新编译内核开启MODULE_FORCE_LOAD选项,强制加载
3、拷贝Module.symversion到内核源码目录,然后在内核源码目录执行make prepare,然后再在编译Module的时候加上KERN_DIR=/usr/src/linux
4、修改Module代码,通过/proc/kallsyms来获得地址,并赋给函数指针来使用
 
参考资料:
http://www.4front-tech.com/forum/viewtopic.php?p=10907&sid=43dc39cc92cbe35d27a4f89ec1208eb0
http://groups.google.com/group/linux.debian.bugs.dist/browse_thread/thread/1c724e019da71903
http://ubuntuforums.org/showthread.php?p=6119045




你可能感兴趣的:(linux内核自学笔记)