Linux 什么是内核部分不匹配?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8563978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:43:45  来源:igfitidea点击:

What is kernel section mismatch?

linuxmodulelinux-kernelkernel

提问by GoTTimw

When compiling a kernel module, I got a WARNING with a note to add a compile option, CONFIG_DEBUG_SECTION_MISMATCH=y. It give me more detailed info about issue:

编译内核模块时,我收到了一条警告,并附有添加编译选项CONFIG_DEBUG_SECTION_MISMATCH=y的注释。它为我提供了有关问题的更多详细信息:

WARNING: \**\*path to module\***(.text+0x8d2): Section mismatch in reference from the function Pch_Spi_Enable_Bios_Wr() to the variable .devinit.data:ich9_pci_tbl.22939
The function Pch_Spi_Enable_Bios_Wr() references
the variable __devinitdata ich9_pci_tbl.22939.
This is often because Pch_Spi_Enable_Bios_Wr lacks a __devinitdata
annotation or the annotation of ich9_pci_tbl.22939 is wrong.

I could not find what exactly kernel section mismatchis, not to mention how to go about fixing it.

我找不到内核部分不匹配的确切含义,更不用说如何修复它了。

采纳答案by Mat

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.hheader 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)

Others follow, with more comments and explanations.

其他人跟随,有更多的评论和解释。

See also the help text for the CONFIG_DEBUG_SECTION_MISMATCHKconfig symbol:

另请参阅CONFIG_DEBUG_SECTION_MISMATCHKconfig 符号的帮助文本:

The section mismatch analysis checks if there are illegal
references from one section to another section.
Linux will during link or during runtime drop some sections
and any use of code/data previously in these sections will
most likely result in an oops.
In the code functions and variables are annotated with
__init, __devinit etc. (see full list in include/linux/init.h)
which results in the code/data being placed in specific sections.
The section mismatch analysis is always done after a full
kernel build but enabling this option will in addition
do the following:

  • Add the option -fno-inline-functions-called-once to gcc
    When inlining a function annotated __init in a non-init
    function we would lose the section information and thus
    the analysis would not catch the illegal reference.
    This option tells gcc to inline less but will also
    result in a larger kernel.
  • Run the section mismatch analysis for each module/built-in.o
    When we run the section mismatch analysis on vmlinux.o we
    lose valueble information about where the mismatch was
    introduced.
    Running the analysis for each module/built-in.o file
    will tell where the mismatch happens much closer to the
    source. The drawback is that we will report the same
    mismatch at least twice.
  • Enable verbose reporting from modpost to help solving
    the section mismatches reported.

节不匹配分析检查
从一个节到另一节是否存在非法引用。
Linux 将在链接期间或运行时删除某些部分,
并且之前在这些部分中使用任何代码/数据
很可能会导致 oops。
在代码中,函数和变量用
__init、__devinit 等注释(参见 include/linux/init.h 中的完整列表)
,这导致代码/数据被放置在特定部分。
部分不匹配分析总是在完整
内核构建后进行,但启用此选项还将
执行以下操作:

  • 将选项 -fno-inline-functions-Called-once 添加到 gcc
    在非 init
    函数中内联注释为 __init 的函数时,我们将丢失节信息,因此
    分析将无法捕获非法引用。
    这个选项告诉 gcc 内联更少,但也会
    导致更大的内核。
  • 为每个模块 /built-in.o
    运行部分不匹配分析 当我们在 vmlinux.o 上运行部分不匹配分析时,我们
    会丢失有关不匹配
    引入位置的有价值的信息。
    对每个模块/built-in.o 文件运行分析
    将告诉更接近
    源的不匹配发生的位置。缺点是我们将
    至少报告两次相同的不匹配。
  • 启用来自 modpost 的详细报告,以帮助解决
    报告的部分不匹配问题。