红联Linux门户
Linux帮助

解决编译kernel出现WARNING:Section mismatch(es)

发布时间:2016-09-22 09:40:23来源:linux网站作者:flfihpv259
在编译内核时出现section mismatch警告:
警告如下:
WARNING: modpost: Found 3 section mismatch(es).
To see full details build your kernel with:
'make CONFIG_DEBUG_SECTION_MISMATCH=y'
 
使用 make CONFIG_DEBUG_SECTION_MISMATCH=y zImage后出现提示信息如下:
WARNING: vmlinux.o(__ksymtab+0x448): Section mismatch in reference from the variable __ksymtab_s3c24xx_ts_set_platdata to the function .init.text:s3c24xx_ts_set_platdata()
The symbol s3c24xx_ts_set_platdata is exported and annotated __init 
Fix this by removing the __init annotation of s3c24xx_ts_set_platdata or drop the export.
WARNING: vmlinux.o(__ksymtab_gpl+0x40): Section mismatch in reference from the variable __ksymtab_s3c_nand_set_platdata to the function .init.text:s3c_nand_set_platdata()
The symbol s3c_nand_set_platdata is exported and annotated __init 
Fix this by removing the __init annotation of s3c_nand_set_platdata or drop the export.
WARNING: vmlinux.o(.data+0x14a0): Section mismatch in reference from the variable s3c2440_dma_driver to the function .init.text:s3c2440_dma_add()
The variable s3c2440_dma_driver references
the function __init s3c2440_dma_add()
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console,
 
原因分析
It means that a function that is in a section with a given lifetime references something that is in a section with a different lifetime.
When the kernel binary is linked, different parts of the code and data are split up into different sections. Some of these sections are kept loaded all the time, but some others are removed once they are no longer needed (things that are only required during boot for example can be freed once boot is done - this saves memory).
If a function that is in a long-lasting section refers to data in one of the discardable sections, there is a problem - it might try to access that data when it has already been released, leading to all kinds of runtime issues.
This is not a warning you’ll fix yourself, unless you wrote that code or are very familiar with it. It gets fixed by correctly annotating the function (or the data it refers to) so that it goes into the right section. The right fix can only be determined with detailed knowledge of that part of the kernel.
For a list of these sections and annotations, refer to the include/linux/init.h header in your kernel source tree:
include/linux/init.h
/* These macros are used to mark some functions or 
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
*
* Usage:
* For functions:
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
*extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
*
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
*
* Don't forget to initialize data not at file scope, i.e. within a function,
* as gcc otherwise puts the data into the bss section and not into the init
* section.
* Also note, that this data cannot be "const".
*/
/* These are for everybody (although not all archs will actually
discard it in modules) */
#define __init  __section(.init.text) __cold notrace
#define __initdata  __section(.init.data)
#define __initconst __section(.init.rodata)
#define __exitdata  __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)
 
解决方法:
知道了原因后就根据提示处理:
前面两个有FIX提示:按其要求,找到相关函数,删除__init就行,如下:
anzyelay@ubuntu:linux-2.6.35.4-2440$ grep 's3c_nand_set_platdata' . -rnI
./tags:1367662:s3c_nand_set_platdataarch/arm/plat-samsung/dev-nand.c/^EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);$/;"v
./tags:1367663:s3c_nand_set_platdataarch/arm/plat-samsung/dev-nand.c/^void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)$/;"f
./arch/arm/plat-samsung/include/plat/nand.h:61: * s3c_nand_set_platdata() - register NAND platform data.
./arch/arm/plat-samsung/include/plat/nand.h:67:extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);
./arch/arm/plat-samsung/dev-nand.c:83:void __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
./arch/arm/plat-samsung/dev-nand.c:130:EXPORT_SYMBOL_GPL(s3c_nand_set_platdata);
./arch/arm/mach-s3c2440/mach-osiris.c:446:  s3c_nand_set_platdata(&osiris_nand_info);
./arch/arm/mach-s3c2440/mach-gta02.c:570:   s3c_nand_set_platdata(&gta02_nand_info);
./arch/arm/mach-s3c2440/mach-mini2440.c:678:s3c_nand_set_platdata(&mini2440_nand_info);
./arch/arm/mach-s3c2440/mach-rx1950.c:541:  s3c_nand_set_platdata(&rx1950_nand_info);
./arch/arm/mach-s3c2440/mach-rx3715.c:206:  s3c_nand_set_platdata(&rx3715_nand_info);
./arch/arm/mach-s3c2440/mach-anubis.c:489:  s3c_nand_set_platdata(&anubis_nand_info);
./arch/arm/mach-s3c2440/mach-at2440evb.c:228:   s3c_nand_set_platdata(&at2440evb_nand_info);
./arch/arm/mach-s3c64xx/mach-hmt.c:253: s3c_nand_set_platdata(&hmt_nand_info);
./arch/arm/plat-s3c24xx/common-smdk.c:187:  s3c_nand_set_platdata(&smdk_nand_info);
./arch/arm/mach-s3c2412/mach-vstms.c:154:   s3c_nand_set_platdata(&vstms_nand_info);
./arch/arm/mach-s3c2412/mach-jive.c:635:s3c_nand_set_platdata(&jive_nand_info);
./arch/arm/mach-s3c2410/mach-qt2410.c:335:  s3c_nand_set_platdata(&qt2410_nand_info);
./arch/arm/mach-s3c2410/mach-bast.c:649:s3c_nand_set_platdata(&bast_nand_info);
./Module.symvers:3166:0x00000000s3c_nand_set_platdata   vmlinux EXPORT_SYMBOL_GPL
./.tmp_System.map:212:c000eb8c T s3c_nand_set_platdata
./.tmp_System.map:21922:c03eb7c8 r __ksymtab_s3c_nand_set_platdata
./.tmp_System.map:23558:c03eef49 r __kstrtab_s3c_nand_set_platdata
./System.map:212:c000eb8c T s3c_nand_set_platdata
./System.map:21922:c03eb7c8 r __ksymtab_s3c_nand_set_platdata
./System.map:23558:c03eef49 r __kstrtab_s3c_nand_set_platdata
anzyelay@ubuntu:linux-2.6.35.4-2440$ vi ./arch/arm/plat-samsung/dev-nand.c +83
83 void  __init s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)   
 
将其修改成:
83 void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand)
 
重样在编译就不会有第二个警告了,第一个类似.这里还有一种方法就是删除导出符号如下:
192 void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
193 {
194 memcpy(&s3c2410ts_info, hard_s3c2410ts_info, sizeof(struct s3c2410_ts_mach_info));
195 s3c_device_ts.dev.platform_data = &s3c2410ts_info;
196 }
197 //EXPORT_SYMBOL(s3c24xx_ts_set_platdata);//将此条语句注释就行,或者删除192行的__init.二选一
 
第三个按提示在变量前加注__initdata就行如下:
anzyelay@ubuntu:linux-2.6.35.4-2440$ grep '__init s3c2440_dma_add' . -rnI
./arch/arm/mach-s3c2440/dma.c:194:static int __init s3c2440_dma_add(struct sys_device *sysdev)
anzyelay@ubuntu:linux-2.6.35.4-2440$ vi ./arch/arm/mach-s3c2440/dma.c +194
194 static int __init s3c2440_dma_add(struct sys_device *sysdev)
195 {
196 s3c2410_dma_init();
197 s3c24xx_dma_order_set(&s3c2440_dma_order);
198 return s3c24xx_dma_init_map(&s3c2440_dma_sel);
199 }
200  
201 static struct sysdev_driver __initdata s3c2440_dma_driver = {//添加__initdata 
202 .add= s3c2440_dma_add,
203 };
 
编译OK,无警告了。
 
本文永久更新地址:http://www.linuxdiyf.com/linux/24369.html