Подтвердить что ты не робот

Что такое несоответствие раздела ядра?

При компиляции модуля ядра я получил предупреждение с примечанием, чтобы добавить параметр компиляции, 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.

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

4b9b3361

Ответ 1

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

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

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

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


Список этих разделов и аннотаций см. в заголовке 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-called-once в gcc
     При встраивании функции, аннотированной __init в не-init  мы потеряли бы информацию раздела и, следовательно,  анализ не поймал бы незаконную ссылку.
     Этот параметр указывает gcc на inline less, но также будет  приводят к большему ядру.
  • Запустите анализ несоответствия раздела для каждого модуля/встроенного .o
     Когда мы запускаем анализ несоответствия раздела на vmlinux.o, мы  потерять ценность информации о том, где несоответствие было  представил.
     Выполнение анализа для каждого модуля/встроенного файла.


     расскажет, где несоответствие происходит намного ближе к  источник. Недостатком является то, что мы сообщим об этом же  несоответствие не реже двух раз.
  • Включить подробные отчеты от modpost, чтобы помочь решить  сообщается о несоответствиях раздела.