Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Fix C jump table annotations for Clang

A C jump table (such as the one used by the BPF interpreter) is a const
global array of absolute code addresses, and this means that the actual
values in the table may not be known until the kernel is booted (e.g.,
when using KASLR or when the kernel VA space is sized dynamically).

When using PIE codegen, the compiler will default to placing such const
global objects in .data.rel.ro (which is annotated as writable), rather
than .rodata (which is annotated as read-only). As C jump tables are
explicitly emitted into .rodata, this used to result in warnings for
LoongArch builds (which uses PIE codegen for the entire kernel) like

Warning: setting incorrect section attributes for .rodata..c_jump_table

due to the fact that the explicitly specified .rodata section inherited
the read-write annotation that the compiler uses for such objects when
using PIE codegen.

This warning was suppressed by explicitly adding the read-only
annotation to the __attribute__((section(""))) string, by commit

c5b1184decc8 ("compiler.h: specify correct attribute for .rodata..c_jump_table")

Unfortunately, this hack does not work on Clang's integrated assembler,
which happily interprets the appended section type and permission
specifiers as part of the section name, which therefore no longer
matches the hard-coded pattern '.rodata..c_jump_table' that objtool
expects, causing it to emit a warning

kernel/bpf/core.o: warning: objtool: ___bpf_prog_run+0x20: sibling call from callable instruction with modified stack frame

Work around this, by emitting C jump tables into .data.rel.ro instead,
which is treated as .rodata by the linker script for all builds, not
just PIE based ones.

Fixes: c5b1184decc8 ("compiler.h: specify correct attribute for .rodata..c_jump_table")
Tested-by: Tiezhu Yang <yangtiezhu@loongson.cn> # on LoongArch
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250221135704.431269-6-ardb+git@google.com
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

authored by

Ard Biesheuvel and committed by
Josh Poimboeuf
73cfc53c 68f3ea7e

+6 -5
+1 -1
include/linux/compiler.h
··· 110 110 /* Unreachable code */ 111 111 #ifdef CONFIG_OBJTOOL 112 112 /* Annotate a C jump table to allow objtool to follow the code flow */ 113 - #define __annotate_jump_table __section(".rodata..c_jump_table,\"a\",@progbits #") 113 + #define __annotate_jump_table __section(".data.rel.ro.c_jump_table") 114 114 #else /* !CONFIG_OBJTOOL */ 115 115 #define __annotate_jump_table 116 116 #endif /* CONFIG_OBJTOOL */
+4 -3
tools/objtool/check.c
··· 2471 2471 * 2472 2472 * - .rodata: can contain GCC switch tables 2473 2473 * - .rodata.<func>: same, if -fdata-sections is being used 2474 - * - .rodata..c_jump_table: contains C annotated jump tables 2474 + * - .data.rel.ro.c_jump_table: contains C annotated jump tables 2475 2475 * 2476 2476 * .rodata.str1.* sections are ignored; they don't contain jump tables. 2477 2477 */ 2478 2478 for_each_sec(file, sec) { 2479 - if (!strncmp(sec->name, ".rodata", 7) && 2480 - !strstr(sec->name, ".str1.")) { 2479 + if ((!strncmp(sec->name, ".rodata", 7) && 2480 + !strstr(sec->name, ".str1.")) || 2481 + !strncmp(sec->name, ".data.rel.ro", 12)) { 2481 2482 sec->rodata = true; 2482 2483 found = true; 2483 2484 }
+1 -1
tools/objtool/include/objtool/special.h
··· 10 10 #include <objtool/check.h> 11 11 #include <objtool/elf.h> 12 12 13 - #define C_JUMP_TABLE_SECTION ".rodata..c_jump_table" 13 + #define C_JUMP_TABLE_SECTION ".data.rel.ro.c_jump_table" 14 14 15 15 struct special_alt { 16 16 struct list_head list;