it-swarm-pt.tech

O que é incompatibilidade de seção do kernel?

Ao compilar um módulo do kernel, recebi um WARNING com uma nota para adicionar uma opção de compilação, CONFIG_DEBUG_SECTION_MISMATCH = y. Ele me fornece informações mais detalhadas sobre o problema:

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.

Não consegui encontrar o que exatamente incompatibilidade da seção do kernel é, sem mencionar como proceder para corrigi-lo.

30
GoTTimw

Isso significa que uma função que está em uma seção com uma vida útil determinada faz referência a algo que está em uma seção com uma vida útil diferente.

Quando o binário do kernel é vinculado, diferentes partes do código e dos dados são divididas em seções diferentes. Algumas dessas seções são mantidas carregadas o tempo todo, mas outras são removidas quando não são mais necessárias (coisas necessárias apenas durante a inicialização, por exemplo, podem ser liberadas após a inicialização - isso economiza memória).

Se uma função que está em uma seção de longa duração se refere a dados em uma das seções descartáveis, há um problema - ela pode tentar acessar esses dados quando já tiverem sido liberados, levando a todos os tipos de problemas de tempo de execução.

Este não é um aviso que você irá corrigir, a menos que tenha escrito esse código ou esteja familiarizado com ele. Ele é corrigido anotando corretamente a função (ou os dados a que se refere) para ir para a seção correta. A correção correta só pode ser determinada com o conhecimento detalhado dessa parte do kernel.


Para obter uma lista dessas seções e anotações, consulte o include/linux/init.h cabeçalho na sua árvore de origem do kernel:

/* 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)

Outros seguem, com mais comentários e explicações.

Veja também o texto de ajuda para o CONFIG_DEBUG_SECTION_MISMATCH Símbolo do Kconfig:

A análise de incompatibilidade de seção verifica se há informações ilegais
referências de uma seção para outra.
O Linux, durante o link ou durante o tempo de execução, descarta algumas seções
e qualquer uso de código/dados anteriormente nestas seções
provavelmente resultam em um oops.
No código, funções e variáveis ​​são anotadas com
__ init, __devinit etc. (veja a lista completa em include/linux/init.h)
que resulta no código/dados sendo colocados em seções específicas.
A análise de incompatibilidade de seção é sempre feita após uma
compilação do kernel, mas ativar essa opção também
faça o seguinte:

  • Adicione a opção -fno-inline-functions-called-once ao gcc
    Ao incorporar uma função anotada __init em um não-init
    perderíamos as informações da seção e, portanto,
    a análise não captaria a referência ilegal.
    Essa opção informa ao gcc para incorporar menos, mas também
    resultam em um kernel maior.
  • Execute a análise de incompatibilidade de seção para cada módulo/interno.o
    Quando executamos a análise de incompatibilidade de seção no vmlinux.o,
    perdem informações valiosas sobre onde a incompatibilidade foi
    apresentado.
    Executando a análise para cada módulo/arquivo interno.o
    dirá onde a incompatibilidade ocorre muito mais perto do
    fonte. A desvantagem é que reportaremos o mesmo
    incompatibilidade pelo menos duas vezes.
  • Ative relatórios detalhados do modpost para ajudar a resolver
    as diferenças de seção relatadas.
37
Mat