A compilação do kernel Linux com o nível de otimização -O0 (sem otimizações) é uma tarefa incomum, frequentemente realizada para fins de depuração detalhada. No entanto, o kernel Linux é extensivamente otimizado para produção, e desabilitar as otimizações padrão (como -Os ou -O2) pode introduzir uma série de erros de compilação. Este guia detalha as modificações necessárias para compilar o kernel Linux versão 4.1 com -O0, abordando problemas comuns que surgem ao desativar otimizações.
1. Modificando o Nível de Otimização Principal
O primeiro passo é ajustar o nível de otimização no Makefile raiz do kernel. As otimizações padrão -Os ou -O2 devem ser removidas e substituídas por -O0 para desabilitar completamente as otimizações do compilador.
# Exemplo de modificação no Makefile de nível superior:
# Substitua otimizações existentes por -O0
# CFLAGS_KERNEL := $(call cc-option,-fno-stack-protector) $(call cc-option,-fno-delete-null-pointer-checks)
# CFLAGS_KERNEL += -Os # Remover ou comentar
CFLAGS_KERNEL += -O0
2. Ajustando Assertivas de Tempo de Compilação
O macro __compiletime_assert no arquivo include/linux/compiler.h pode gerar erros quando as otimizações são desabilitadas, pois sua lógica complexa baseada em __compiletime_error pode não ser interpretada corretamente pelo compilador sem otimizações. Para contornar isso, simplificamos a assertiva para uma verificação mais direta que dispara um BUG_ON em caso de falha.
Modifique include/linux/compiler.h da seguinte forma:
#ifdef KERNEL_DEBUG_NO_OPTIMIZATION
// Simplifica a assertiva de tempo de compilação para depuração com -O0
#define KERNEL_ASSERT_ON_COMPILE_FAIL(condition_expr, message_str, pfx, sfx) BUG_ON(!(condition_expr))
#else
// Comportamento padrão de assertiva de tempo de compilação
#define KERNEL_ASSERT_ON_COMPILE_FAIL(condition_expr, message_str, pfx, sfx) \
do { \
_Bool __assert_check = !(condition_expr); \
extern void pfx ## sfx(void) __compiletime_error(message_str); \
if (__assert_check) \
pfx ## sfx(); \
__compiletime_error_fallback(__assert_check); \
} while (0)
#endif
Esta alteração desativa a verificação avançada em favor de um BUG_ON mais simples quando KERNEL_DEBUG_NO_OPTIMIZATION é definido, permitindo a continuidade da compilação.
3. Tratando Erros de Jump Label (asm goto) no ARM64
A arquitetura ARM64 utiliza o recurso asm goto para otimizações de jump label, que são cruciais para o desempenho de macros como likely() e unlikely(). Essas otimizações utilizam instruções de salto diretas em tabelas (JUMP TABLE) para evitar desvios condicionais. No entanto, com -O0, o compilador pode ter dificuldade em processar a sintaxe asm goto, resultando em erros. Para resolver isso, desabilitamos temporariamente essa otimização, fazendo com que a função de branch estático retorne sempre true.
No arquivo arch/arm64/include/asm/jump_label.h, comente o bloco asm goto:
static __always_inline bool kernel_static_branch_control(struct static_key *key_ref)
{
#ifndef DISABLE_ASM_GOTO_BRANCHES // Ativar por padrão, desativar para -O0
asm goto("1: nop\n\t"
".pushsection __custom_jump_table, \"aw\"\n\t"
".align 3\n\t"
".quad 1b, %l[target_branch], %c0\n\t"
".popsection\n\t"
: : "i"(key_ref) : : target_branch);
return false;
target_branch:
#endif // DISABLE_ASM_GOTO_BRANCHES
// Caminho de fallback para quando a otimização asm goto é desativada
return true;
}
Esta modificação garante que, ao compilar com -O0, a lógica de branch estático não tente usar asm goto, evitando falhas.
4. Corrigindo Erros de Contagem de Mismatch do Modpost
A ferramenta modpost, responsável pela verificação de módulos do kernel, pode relatar "section mismatch(es)" (incompatibilidades de seção) que são benignas ou um subproduto da compilação com -O0. Essas mensagens podem parar o processo de construção. Para contornar, podemos suprimir essas advertências e forçar o modpost a retornar um status de sucesso (erro 0).
Modifique scripts/mod/modpost.c da seguinte forma:
if (dump_output_file)
write_compilation_dump(dump_output_file);
#ifdef SUPPRESS_MODPOST_MISMATCH_WARNINGS
// Suprimir erros de mismatch para compilações -O0
// Esses podem ser falsos positivos sem otimização
return 0; // Retorna sucesso incondicionalmente
#else
if (section_mismatch_count > 0 && !section_mismatch_verbose_mode)
warn("modpost: Encontrados %d mismatch(es) de seção.\n"
"Para detalhes completos, compile o kernel com:\n"
"'make KERNEL_CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
section_mismatch_count);
return exit_code; // Retorna o código de erro original
#endif
Ao definir SUPPRESS_MODPOST_MISMATCH_WARNINGS, garantimos que o modpost não interrompa a compilação devido a incompatibilidades que podem ser ignoradas no contexto de uma build -O0.
5. Solucionando Erros de Compilação no Subsistema de Arquivos (FS - Ext4)
O subsistema de arquivos ext4, particularmente em relação aos recursos de criptografia (controlados por CONFIG_EXT4_FS_ENCRYPTION), pode gerar erros de compilação com -O0. Quando a criptografia é desativada, muitas funções relacionadas são definidas como static inline stubs (funções vazias ou que retornam valores padrão). O compilador, operando sem otimizações, pode ter dificuldade em lidar com essas definições de stubs, resultando em erros de "símbolo indefinido" ou "múltipla definição" em algumas situações. As correções geralmente envolvem ajustar as cláusulas #else dos blocos #ifdef CONFIG_EXT4_FS_ENCRYPTION para garantir que essas funções stub problemáticas sejam completamente removidas ou tratadas de forma diferenet.
Um exemplo comum de ajuste é comentar ou remover declarações de static inline em arquivos de cabeçalho (como fs/ext4/ext4.h) que causam conflitos quando a criptografia não está habilitada:
// Exemplo em fs/ext4/ext4.h, dentro de um bloco #else CONFIG_EXT4_FS_ENCRYPTION
#ifndef CONFIG_EXT4_FS_ENCRYPTION
// ... outras definições ...
// Linha original que pode causar problemas com -O0:
// static inline int ext4_inherit_context(struct inode *p, struct inode *c) { return 0; }
// Para corrigir, comente ou remova a declaração:
// // static inline int ext4_inherit_context(struct inode *p, struct inode *c) { return 0; }
// Da mesma forma, outras funções como ext4_get_crypto_ctx ou ext4_read_workqueue
// podem precisar de ajustes semelhantes para evitar erros de compilação.
#endif // !CONFIG_EXT4_FS_ENCRYPTION
Essas modificações específicas impedem que o compilador encontre conflitos com funções que não deveriam estar ativas ou que são mal interpretadas sem otimizações, permitindo que a compilação do subsistema ext4 seja concluída com sucesso sob -O0.