[PATCH v4 13/14] objtool/klp: Keep LoongArch tablejump annotation table entries

George Guo <[email protected]> Fri, 24 Jul 2026 19:41:26 +0800
Newsgroups org.kernel.vger.live-patching,dev.linux.lists.llvm,dev.linux.lists.loongarch,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: George Guo <[email protected]>

With -mannotate-tablejump, LoongArch compilers emit a
.discard.tablejump_annotate section.  Each entry is a pair of 8-byte
words: the address of a jump instruction and the address of its jump
table.  objtool reads these pairs to find switch jump tables when
decoding.

klp-diff creates one fake symbol per 8-byte word and clones a word only
if should_keep_special_sym() accepts it.  The default rule keeps a word
only if it references a function that was cloned into the output
module.  The instruction-side word references the function and is
kept.  The table-side word references the jump table via its .rodata
section symbol, which is not a function symbol, so it is dropped.

The cloned annotate section then holds only instruction-side words,
compacted together.  The pairing is destroyed.  Parsing the malformed
section crashes objtool on the patch module and no .ko is produced:

  Building patch module: livepatch-shadow-newpid.ko
  livepatch-shadow-newpid.o: error: SIGSEGV: objtool crash!

Keep all .discard.tablejump_annotate words whose referenced symbol has
been cloned.

Reproduced with the shadow-newpid test, which patches
proc_pid_status().  That function contains two switch jump tables.

Before, klp-diff clones only the instruction-side words:

  DEBUG: vmlinux.o: _discard_tablejump_annotate_57441 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x0: proc_pid_status+0xc70 [FUNC GLOBAL]
  DEBUG: vmlinux.o: _discard_tablejump_annotate_57443 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x8: proc_pid_status+0xd2c [FUNC GLOBAL]

After, the full pairs are kept, including the .rodata table words:

  DEBUG: vmlinux.o: _discard_tablejump_annotate_57441 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x0: proc_pid_status+0xc70 [FUNC GLOBAL]
  DEBUG: vmlinux.o: _discard_tablejump_annotate_57442 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x8: .rodata.proc_pid_status+0x0 [SECTION]
  DEBUG: vmlinux.o: _discard_tablejump_annotate_57443 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x10: proc_pid_status+0xd2c [FUNC GLOBAL]
  DEBUG: vmlinux.o: _discard_tablejump_annotate_57444 [+DATA]
  DEBUG: vmlinux.o:         .discard.tablejump_annotate+0x18: .rodata.proc_pid_status+0x80 [SECTION]

and the patch module builds.

Co-developed-by: Kexin Liu <[email protected]>
Signed-off-by: Kexin Liu <[email protected]>
Signed-off-by: George Guo <[email protected]>
---
 tools/objtool/klp-diff.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 92cf0fc3ff2f..f151ffc71184 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1956,6 +1956,7 @@ static int create_fake_symbols(struct elf *elf)
 static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
 {
 	bool annotate_insn = !strcmp(sym->sec->name, ".discard.annotate_insn");
+	bool tablejump_annotate = !strcmp(sym->sec->name, ".discard.tablejump_annotate");
 	struct reloc *reloc;
 
 	if (is_sec_sym(sym) || !sym->sec->rsec)
@@ -1968,6 +1969,16 @@ static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
 		if (!reloc->sym->clone || is_undef_sym(reloc->sym->clone))
 			continue;
 
+		/*
+		 * .discard.tablejump_annotate (LoongArch -mannotate-tablejump)
+		 * holds pairs of words: a jump instruction and its jump table.
+		 * The table word references the table via its .rodata section
+		 * symbol, which the is_func_sym() rule below would drop,
+		 * breaking the pairing.  Keep both words of each entry.
+		 */
+		if (tablejump_annotate)
+			return true;
+
 		/*
 		 * Keep special section references to cloned functions.
 		 * In some cases annotate_insn can also reference cloned alt
-- 
2.53.0