What is kernel section mismatch?

GoTTimw picture GoTTimw · Dec 19, 2011 · Viewed 18.9k times · Source

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:

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 mismatch is, not to mention how to go about fixing it.

Answer

Mat picture Mat · Dec 19, 2011

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:

/* 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_MISMATCH Kconfig symbol:

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.