Что такое несоответствие раздела ядра? - PullRequest
28 голосов
/ 19 декабря 2011

При компиляции модуля ядра я получил ПРЕДУПРЕЖДЕНИЕ с примечанием о добавлении опции компиляции, 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.

Я не смог найти, что именно является несоответствием раздела ядра , не говоря уже о том, как его исправить.

1 Ответ

36 голосов
/ 19 декабря 2011

Это означает, что функция, которая находится в разделе с заданным временем жизни, ссылается на то, что находится в разделе с другим временем жизни.

Когда двоичный файл ядра связан, разные части кода и данные разделяются на разные секции. Некоторые из этих разделов постоянно загружены, но некоторые удаляются, когда они больше не нужны (например, вещи, которые требуются только во время загрузки, могут быть освобождены после завершения загрузки - это экономит память).

Если функция, находящаяся в длительном разделе, ссылается на данные в одном из отбрасываемых разделов, существует проблема - она ​​может попытаться получить доступ к этим данным, когда они уже были выпущены, что приведет к всевозможным проблемам во время выполнения. .

Это не предупреждение, которое вы исправите сами, если только вы не написали этот код или не очень хорошо с ним знакомы. Это исправляется путем правильного аннотирования функции (или данных, на которые она ссылается), чтобы она попала в правильный раздел. Правильное исправление может быть определено только при детальном знании этой части ядра.


Список этих разделов и аннотаций см. В заголовке 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)

Далее следуют другие, с дополнительными комментариями и объяснениями.

См. Также текст справки для символа CONFIG_DEBUG_SECTION_MISMATCH Kconfig:

Анализ несоответствия раздела проверяет, являются ли незаконными
ссылки из одного раздела в другой раздел.
Linux во время ссылки или во время выполнения отбросит некоторые разделы
и любое использование кода / данных ранее в этих разделах будет
Скорее всего, результат в ой.
В коде функции и переменные помечены
__init, __devinit и т. д. (см. полный список в include / linux / init.h)
в результате код / ​​данные помещаются в определенные разделы.
Анализ несоответствия раздела всегда выполняется после полного
сборка ядра, но включение этой опции будет дополнительно
выполните следующие действия:

  • Добавить опцию -fno-inline-functions-call-Once в gcc
    При встраивании функции, аннотированной __init в не-init
    функция, которую мы потеряли бы информацию раздела и, следовательно,
    анализ не уловит нелегальную ссылку.
    Эта опция указывает gcc на встроенное меньше, но также
    результат в большем ядре.
  • Запуск анализа несоответствия сечений для каждого модуля / встроенного. O
    Когда мы запускаем анализ несоответствия раздела на vmlinux.o, мы
    потерять ценную информацию о несоответствии
    представил.
    Запуск анализа для каждого файла модуля / встроенного .o
    скажет, где происходит несоответствие гораздо ближе к
    источник. Недостатком является то, что мы сообщим о том же
    несоответствие по крайней мере дважды.
  • Включить подробные отчеты из modpost, чтобы помочь решить
    сообщается о несоответствиях раздела.
...