All of lore.kernel.org
 help / color / mirror / Atom feed
From: George Guo <dongtai.guo@linux.dev>
To: chenhuacai@kernel.org, jpoimboe@kernel.org, peterz@infradead.org,
	jikos@kernel.org, mbenes@suse.cz, pmladek@suse.com
Cc: kernel@xen0n.name, joe.lawrence@redhat.com, rostedt@goodmis.org,
	ardb@kernel.org, nathan@kernel.org,
	nick.desaulniers+lkml@gmail.com, yangtiezhu@loongson.cn,
	jiaxun.yang@flygoat.com, liukexin@kylinos.cn,
	guodongtai@kylinos.cn, xry111@xry111.site, wangyuli@aosc.io,
	loongarch@lists.linux.dev, live-patching@vger.kernel.org,
	llvm@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL
Date: Tue,  7 Jul 2026 15:20:31 +0800	[thread overview]
Message-ID: <20260707072031.231066-13-dongtai.guo@linux.dev> (raw)
In-Reply-To: <20260707072031.231066-1-dongtai.guo@linux.dev>

From: George Guo <guodongtai@kylinos.cn>

On LoongArch, the "key - ." field of a __jump_table entry can come out
as two relocations at the same offset, R_LARCH_ADD64 plus
R_LARCH_SUB64.  clang's integrated assembler emits this pair when the
key symbol is not defined in the same translation unit (for example
__tracepoint_netif_rx); GAS, and clang for locally-defined keys,
produce a single R_LARCH_64_PCREL instead, which is why GCC builds do
not hit this.  objtool's elf_create_reloc() allows only one relocation
per offset, so cloning such an entry fails with:

  vmlinux.o: error: objtool: __jump_table_23683+0x8: duplicate reloc

When the SUB half points at the relocation's own position (the
"sym - ." pattern), the pair means the same thing as one PC-relative
relocation.  Add arch_normalize_paired_reloc() which rewrites the ADD
half to R_LARCH_32_PCREL/R_LARCH_64_PCREL and skips the SUB half.  The
LoongArch module loader supports both forms.

Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
 tools/objtool/arch/loongarch/decode.c         | 62 +++++++++++++++++++
 .../objtool/arch/loongarch/include/arch/elf.h | 18 ++++++
 tools/objtool/klp-diff.c                      | 13 ++++
 3 files changed, 93 insertions(+)

diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 12facd0cc8d1..273398ea4486 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -39,6 +39,68 @@ u64 arch_adjusted_addend(struct reloc *reloc)
 	return reloc_addend(reloc);
 }
 
+/*
+ * A cross-section difference like the "key - ." field of a __jump_table
+ * entry may come out as a paired R_LARCH_ADD plus R_LARCH_SUB relocation
+ * at the same offset: clang's integrated assembler does this when the
+ * symbol is not defined in the same translation unit (GAS, and clang for
+ * locally-defined symbols, emit a single PCREL instead).  objtool allows
+ * only one relocation per offset, so the pair breaks cloning.
+ *
+ * When the SUB half points at the reloc's own position ("sym - ."), the
+ * pair means the same as a single PC-relative relocation, which the
+ * module loader also supports: rewrite the ADD half to R_LARCH_*_PCREL
+ * and tell the caller to skip the SUB half.
+ *
+ * Return 1 to skip the reloc, 0 to proceed, -1 on error.
+ */
+int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc)
+{
+	struct section *rsec = reloc->sec;
+	unsigned int sub_type, pcrel_type;
+	struct reloc *sub, *add;
+
+	switch (reloc_type(reloc)) {
+	case R_LARCH_ADD32:
+		sub_type = R_LARCH_SUB32;
+		pcrel_type = R_LARCH_32_PCREL;
+		break;
+	case R_LARCH_ADD64:
+		sub_type = R_LARCH_SUB64;
+		pcrel_type = R_LARCH_64_PCREL;
+		break;
+	case R_LARCH_SUB32:
+	case R_LARCH_SUB64:
+		/*
+		 * Skip only if the paired ADD (the preceding reloc) has
+		 * been rewritten to PCREL; otherwise leave the pair
+		 * intact so a failed conversion stays loud.
+		 */
+		add = reloc_idx(reloc) ? reloc - 1 : NULL;
+		if (add && reloc_offset(add) == reloc_offset(reloc) &&
+		    (reloc_type(add) == R_LARCH_32_PCREL ||
+		     reloc_type(add) == R_LARCH_64_PCREL))
+			return 1;
+		return 0;
+	default:
+		return 0;
+	}
+
+	/* The paired SUB reloc immediately follows the ADD */
+	sub = rsec_next_reloc(rsec, reloc);
+	if (!sub || reloc_offset(sub) != reloc_offset(reloc) ||
+	    reloc_type(sub) != sub_type)
+		return 0;
+
+	/* Only a "sym - ." difference is PC-relative */
+	if (sub->sym->sec != rsec->base ||
+	    sub->sym->offset + reloc_addend(sub) != reloc_offset(sub))
+		return 0;
+
+	set_reloc_type(elf, reloc, pcrel_type);
+	return 0;
+}
+
 bool arch_pc_relative_reloc(struct reloc *reloc)
 {
 	return false;
diff --git a/tools/objtool/arch/loongarch/include/arch/elf.h b/tools/objtool/arch/loongarch/include/arch/elf.h
index ec79062c9554..0103f27fccfc 100644
--- a/tools/objtool/arch/loongarch/include/arch/elf.h
+++ b/tools/objtool/arch/loongarch/include/arch/elf.h
@@ -15,6 +15,18 @@
 #ifndef R_LARCH_64
 #define R_LARCH_64		2
 #endif
+#ifndef R_LARCH_ADD32
+#define R_LARCH_ADD32		50
+#endif
+#ifndef R_LARCH_ADD64
+#define R_LARCH_ADD64		51
+#endif
+#ifndef R_LARCH_SUB32
+#define R_LARCH_SUB32		55
+#endif
+#ifndef R_LARCH_SUB64
+#define R_LARCH_SUB64		56
+#endif
 #ifndef R_LARCH_32_PCREL
 #define R_LARCH_32_PCREL	99
 #endif
@@ -34,4 +46,10 @@
 #define R_TEXT32		R_LARCH_32_PCREL
 #define R_TEXT64		R_LARCH_32_PCREL
 
+#define ARCH_HAS_PAIRED_RELOCS	1
+
+struct elf;
+struct reloc;
+int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc);
+
 #endif /* _OBJTOOL_ARCH_ELF_H */
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 0fa3ce324346..02b2150e3ca3 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1504,6 +1504,13 @@ static bool is_uncorrelated_section(struct section *sec)
 	       strstarts(sec->name, ".data..Lanon.");		/* Clang */
 }
 
+#ifndef ARCH_HAS_PAIRED_RELOCS
+static inline int arch_normalize_paired_reloc(struct elf *elf, struct reloc *reloc)
+{
+	return 0;
+}
+#endif
+
 /*
  * Convert a relocation symbol reference to the needed format: either a section
  * symbol or the underlying symbol itself.  Return -1 error, 0 success, 1 skip.
@@ -1511,10 +1518,16 @@ static bool is_uncorrelated_section(struct section *sec)
 static int convert_reloc_sym(struct elf *elf, struct reloc *reloc)
 {
 	struct section *sec = reloc->sym->sec;
+	int ret;
 
 	if (reloc_type(reloc) == R_NONE)
 		return 1;
 
+	/* Fold paired ADD/SUB relocs (LoongArch) into a single PCREL */
+	ret = arch_normalize_paired_reloc(elf, reloc);
+	if (ret)
+		return ret;
+
 	if (is_uncorrelated_section(sec))
 		return convert_reloc_sym_to_secsym(elf, reloc);
 
-- 
2.25.1


  parent reply	other threads:[~2026-07-07  7:23 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  7:20 [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support George Guo
2026-07-07  7:20 ` [PATCH v3 01/12] objtool/LoongArch: Add arch_adjusted_addend() for KLP support George Guo
2026-07-07  7:20 ` [PATCH v3 02/12] LoongArch: Mark special sections " George Guo
2026-07-08 22:32   ` Joe Lawrence
2026-07-13 14:33     ` George Guo
2026-07-07  7:20 ` [PATCH v3 03/12] livepatch/klp-build: disable direct-extern-access for LoongArch to fix kernel panic George Guo
2026-07-07  7:20 ` [PATCH v3 04/12] livepatch/klp-build: build LoongArch with -fPIC to keep GOT-indirect symbol references George Guo
2026-07-08 15:05   ` Joe Lawrence
2026-07-10  7:38     ` George Guo
2026-07-07  7:20 ` [PATCH v3 05/12] LoongArch: Fix EFI linking with -fdata-sections George Guo
2026-07-08 13:54   ` Joe Lawrence
2026-07-08 16:07     ` Joe Lawrence
2026-07-10  7:46       ` George Guo
2026-07-07  7:20 ` [PATCH v3 06/12] objtool/klp: Add LoongArch jump opcode bytes support George Guo
2026-07-07  7:20 ` [PATCH v3 07/12] klp-build: Add LoongArch syscall patching macro George Guo
2026-07-08 19:18   ` Joe Lawrence
2026-07-10  7:49     ` George Guo
2026-07-07  7:20 ` [PATCH v3 08/12] LoongArch: Add livepatch build (KLP) support George Guo
2026-07-07  7:20 ` [PATCH v3 09/12] LoongArch: Select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY George Guo
2026-07-07  7:20 ` [PATCH v3 10/12] objtool/klp: Convert local label references in special sections George Guo
2026-07-07  7:20 ` [PATCH v3 11/12] objtool/klp: Fix ANNOTATE_DATA_SPECIAL parsing for local label references George Guo
2026-07-07  7:20 ` George Guo [this message]
2026-07-08 13:29   ` [PATCH v3 12/12] objtool/klp: Fold LoongArch paired ADD/SUB relocations into PCREL Xi Ruoyao
2026-07-09  9:43 ` [PATCH v3 00/12] LoongArch: Add livepatch build (KLP) support Huacai Chen
2026-07-09 10:35   ` WangYuli
2026-07-09 13:21   ` George Guo
2026-07-10 14:34     ` Huacai Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707072031.231066-13-dongtai.guo@linux.dev \
    --to=dongtai.guo@linux.dev \
    --cc=ardb@kernel.org \
    --cc=chenhuacai@kernel.org \
    --cc=guodongtai@kylinos.cn \
    --cc=jiaxun.yang@flygoat.com \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=kernel@xen0n.name \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liukexin@kylinos.cn \
    --cc=live-patching@vger.kernel.org \
    --cc=llvm@lists.linux.dev \
    --cc=loongarch@lists.linux.dev \
    --cc=mbenes@suse.cz \
    --cc=nathan@kernel.org \
    --cc=nick.desaulniers+lkml@gmail.com \
    --cc=peterz@infradead.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=wangyuli@aosc.io \
    --cc=xry111@xry111.site \
    --cc=yangtiezhu@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.