From nobody Sat Jun 13 22:11:39 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B4D6429811; Tue, 5 May 2026 10:56:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777978573; cv=none; b=cUi+CzvqHDmtMIz2KstSf4ueBtaFd6aEV9hsikDmkTDS9620Jk+5/11Wvc7/2arBssNVZw0NFCWdzqQ2H33GZXSpddr3/cPFFt0TeRujWgKIcXXAZ6LDCTInh01g6hwf+XhTJ5DwZMHNJ7d5PC1rx6bs4ZlHYyTXddFegYuUiS8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777978573; c=relaxed/simple; bh=3CNjne2yuo38NDJomeLN2RHtV/q1jtny0oIK9tq+NYw=; h=Date:From:To:Subject:Cc:MIME-Version:Message-ID:Content-Type; b=iymJCkNHUCKf8965V2SyWtOkcefDSlWSFst9HrU/EkGCXLuMIA/7Ek8GdNbhhkLKIowb8umoy+iBOQI/uTFSS2rVAHmWZAJJZa9/dg4eQkIdrZNEd/SxXtynPza/8sSWMc45lbAtyrPC1b9yYijEJTemz8IaJF5deLWCi6Z1p3o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=fOsFj7zy; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=X5TAxqpJ; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="fOsFj7zy"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="X5TAxqpJ" Date: Tue, 05 May 2026 10:56:08 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1777978569; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7qMuMIN8MEzX9azgMgZbS4sAJrUQESzef74+/ZOhZeg=; b=fOsFj7zyxiMkcmthoKBogfdzQeVs4g4+tO42jOeMLkNtWTDKwdVeH8PiLSG+BvG2bThvk0 lcuDlhgkpZmjG0+nwoTKSpmDOOVpVRNA937pCY6dfZP0HevwCbozAtnJzBjmkwUXwTpL9C hMCatqIiWAlickEVGWJjpoS7ntQtH9e8JZpVyfAwBcEynfzTmHmUtEOHkx5SF/NInBSi65 a8IhSE7Q+O6O8nsIikL0oheNTck7tARW7R64KoFO24o91p3mfEX1VoIoRk2KBUNTHHy+MB /MgchTKQGhoyU3tkGezu6QbcDxFknwHYplFIV4WMOU+7fMSORQXCEZX4mDDt8w== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1777978569; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7qMuMIN8MEzX9azgMgZbS4sAJrUQESzef74+/ZOhZeg=; b=X5TAxqpJf0xbTtjULNVIxi5ZDOFIRqmrBkrk1e45nGe0kqxO5R3zi7I6rPdwzgXgX+K2As aySgpHEU+DnTzNDQ== From: "tip-bot2 for Josh Poimboeuf" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: objtool/core] objtool/klp: Extricate checksum calculation from validate_branch() Cc: Song Liu , Josh Poimboeuf , x86@kernel.org, linux-kernel@vger.kernel.org Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177797856843.424702.17580945872489299317.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the objtool/core branch of tip: Commit-ID: 30cae58cdc13b91035faae3dcc8a96fe8a2daae3 Gitweb: https://git.kernel.org/tip/30cae58cdc13b91035faae3dcc8a96fe8= a2daae3 Author: Josh Poimboeuf AuthorDate: Fri, 03 Apr 2026 12:11:17 -07:00 Committer: Josh Poimboeuf CommitterDate: Mon, 04 May 2026 21:16:05 -07:00 objtool/klp: Extricate checksum calculation from validate_branch() In preparation for porting the checksum code to other arches, make its functionality independent from the CFG reverse engineering code. Move it into a standalone calculate_checksums() function which iterates all functions and instructions directly, rather than being called inline from do_validate_branch(). Since checksum_update_insn() is no longer called during CFG traversal, it needs to manually iterate the alternatives. Acked-by: Song Liu Signed-off-by: Josh Poimboeuf --- tools/objtool/check.c | 106 ++++++++++++++++------ tools/objtool/include/objtool/checksum.h | 6 +- 2 files changed, 80 insertions(+), 32 deletions(-) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 93a054a..f019e1f 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1350,10 +1350,7 @@ static struct reloc *insn_reloc(struct objtool_file = *file, struct instruction *i { struct reloc *reloc; =20 - if (insn->no_reloc) - return NULL; - - if (!file) + if (!file || insn->no_reloc || insn->fake) return NULL; =20 reloc =3D find_reloc_by_dest_range(file->elf, insn->sec, @@ -2622,9 +2619,17 @@ static void mark_holes(struct objtool_file *file) =20 static bool validate_branch_enabled(void) { - return opts.stackval || - opts.orc || - opts.uaccess || + return opts.stackval || + opts.orc || + opts.uaccess; +} + +static bool alts_needed(void) +{ + return validate_branch_enabled() || + opts.noinstr || + opts.hack_jump_label || + opts.disas || opts.checksum; } =20 @@ -2658,7 +2663,7 @@ static int decode_sections(struct objtool_file *file) * Must be before add_jump_destinations(), which depends on 'func' * being set for alternatives, to enable proper sibling call detection. */ - if (validate_branch_enabled() || opts.noinstr || opts.hack_jump_label || = opts.disas) { + if (alts_needed()) { if (add_special_section_alts(file)) return -1; } @@ -3654,6 +3659,7 @@ static bool skip_alt_group(struct instruction *insn) return alt_insn->type =3D=3D INSN_CLAC || alt_insn->type =3D=3D INSN_STAC; } =20 +#ifdef BUILD_KLP static int checksum_debug_init(struct objtool_file *file) { char *dup, *s; @@ -3701,8 +3707,10 @@ static void checksum_update_insn(struct objtool_file= *file, struct symbol *func, struct instruction *insn) { struct reloc *reloc =3D insn_reloc(file, insn); + struct alternative *alt; unsigned long offset; struct symbol *sym; + static bool in_alt; =20 if (insn->fake) return; @@ -3715,7 +3723,7 @@ static void checksum_update_insn(struct objtool_file = *file, struct symbol *func, if (call_dest) checksum_update(func, insn, call_dest->demangled_name, strlen(call_dest->demangled_name)); - return; + goto alts; } =20 sym =3D reloc->sym; @@ -3726,21 +3734,78 @@ static void checksum_update_insn(struct objtool_fil= e *file, struct symbol *func, =20 str =3D sym->sec->data->d_buf + sym->offset + offset; checksum_update(func, insn, str, strlen(str)); - return; + goto alts; } =20 if (is_sec_sym(sym)) { sym =3D find_symbol_containing(reloc->sym->sec, offset); if (!sym) - return; + goto alts; =20 offset -=3D sym->offset; } =20 checksum_update(func, insn, sym->demangled_name, strlen(sym->demangled_na= me)); checksum_update(func, insn, &offset, sizeof(offset)); + +alts: + for (alt =3D insn->alts; alt; alt =3D alt->next) { + struct alt_group *alt_group =3D alt->insn->alt_group; + + /* Prevent __ex_table recursion, e.g. LOAD_SEGMENT() */ + if (in_alt) + break; + in_alt =3D true; + + checksum_update(func, insn, &alt->type, sizeof(alt->type)); + + if (alt_group && alt_group->orig_group) { + struct instruction *alt_insn; + + checksum_update(func, insn, &alt_group->feature, sizeof(alt_group->feat= ure)); + + for (alt_insn =3D alt->insn; alt_insn; alt_insn =3D next_insn_same_sec(= file, alt_insn)) { + checksum_update_insn(file, func, alt_insn); + if (!alt_group->last_insn || alt_insn =3D=3D alt_group->last_insn) + break; + } + } else { + checksum_update_insn(file, func, alt->insn); + } + + in_alt =3D false; + } } =20 +static int calculate_checksums(struct objtool_file *file) +{ + struct instruction *insn; + struct symbol *func; + + if (checksum_debug_init(file)) + return -1; + + for_each_sym(file->elf, func) { + /* + * Skip cold subfunctions and aliases: they share the + * parent's checksum via func_for_each_insn() which + * follows func->cfunc into the cold subfunction. + */ + if (!is_func_sym(func) || is_cold_func(func) || + is_alias_sym(func) || !func->len) + continue; + + checksum_init(func); + + func_for_each_insn(file, func, insn) + checksum_update_insn(file, func, insn); + + checksum_finish(func); + } + return 0; +} +#endif /* BUILD_KLP */ + static int validate_branch(struct objtool_file *file, struct symbol *func, struct instruction *insn, struct insn_state state); static int do_validate_branch(struct objtool_file *file, struct symbol *fu= nc, @@ -4022,9 +4087,6 @@ static int do_validate_branch(struct objtool_file *fi= le, struct symbol *func, insn->trace =3D 0; next_insn =3D next_insn_to_validate(file, insn); =20 - if (opts.checksum && func && insn->sec) - checksum_update_insn(file, func, insn); - if (func && insn_func(insn) && func !=3D insn_func(insn)->pfunc) { /* Ignore KCFI type preambles, which always fall through */ if (is_prefix_func(func)) @@ -4090,9 +4152,6 @@ static int validate_unwind_hint(struct objtool_file *= file, struct symbol *func =3D insn_func(insn); int ret; =20 - if (opts.checksum) - checksum_init(func); - ret =3D validate_branch(file, func, insn, *state); if (ret) BT_INSN(insn, "<=3D=3D=3D (hint)"); @@ -4535,9 +4594,6 @@ static int validate_symbol(struct objtool_file *file,= struct section *sec, =20 func =3D insn_func(insn); =20 - if (opts.checksum) - checksum_init(func); - if (opts.trace && !fnmatch(opts.trace, sym->name, 0)) { trace_enable(); TRACE("%s: validation begin\n", sym->name); @@ -4550,9 +4606,6 @@ static int validate_symbol(struct objtool_file *file,= struct section *sec, TRACE("%s: validation %s\n\n", sym->name, ret ? "failed" : "end"); trace_disable(); =20 - if (opts.checksum) - checksum_finish(func); - return ret; } =20 @@ -5007,10 +5060,6 @@ int check(struct objtool_file *file) cfi_hash_add(&init_cfi); cfi_hash_add(&func_cfi); =20 - ret =3D checksum_debug_init(file); - if (ret) - goto out; - ret =3D decode_sections(file); if (ret) goto out; @@ -5101,6 +5150,9 @@ int check(struct objtool_file *file) warnings +=3D check_abs_references(file); =20 if (opts.checksum) { + ret =3D calculate_checksums(file); + if (ret) + goto out; ret =3D create_sym_checksum_section(file); if (ret) goto out; diff --git a/tools/objtool/include/objtool/checksum.h b/tools/objtool/inclu= de/objtool/checksum.h index 0bd16fe..3f25df9 100644 --- a/tools/objtool/include/objtool/checksum.h +++ b/tools/objtool/include/objtool/checksum.h @@ -33,11 +33,7 @@ static inline void checksum_finish(struct symbol *func) =20 #else /* !BUILD_KLP */ =20 -static inline void checksum_init(struct symbol *func) {} -static inline void checksum_update(struct symbol *func, - struct instruction *insn, - const void *data, size_t size) {} -static inline void checksum_finish(struct symbol *func) {} +static inline int calculate_checksums(struct objtool_file *file) { return = -ENOSYS; } =20 #endif /* !BUILD_KLP */ =20