[RFC PATCH 2/3] objtool/klp: Include symbol identities in reference checksums
From: Longjun Luo
Date: Mon Oct 26 2026 - 06:23:15 EST
A call or data reference can switch to a same-named symbol without
changing the target's demangled name. Hashing that name alone can miss
the change, even when the symbols have been correlated correctly.
Prepare identities before calculating checksums and hash the target's
source/scope/demangled_name path. This distinguishes TU-local and
external targets while allowing compiler suffixes to change. Keep the
single-object checksum command and its on-disk format unchanged.
Tested with GCC and Clang, including same-named call/data targets,
function-pointer tables, and four full-kernel vmlinux.o build pairs.
This patch introduces no new test failures. The three policy
rejections from the identity correlation patch remain; sympos and
sympos-vmlinux now fail earlier, in klp checksum, because identities
are prepared there.
Assisted-by: LLM
Signed-off-by: Longjun Luo <luolongjuna@xxxxxxxxx>
---
tools/objtool/include/objtool/klp-identity.h | 1 +
tools/objtool/include/objtool/klp.h | 2 ++
tools/objtool/klp-checksum.c | 25 +++++++++++++-------
tools/objtool/klp-diff.c | 2 +-
tools/objtool/klp-identity.c | 7 ++++++
5 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/tools/objtool/include/objtool/klp-identity.h b/tools/objtool/include/objtool/klp-identity.h
index 0c7be8cfd49b..8483ce92f2e5 100644
--- a/tools/objtool/include/objtool/klp-identity.h
+++ b/tools/objtool/include/objtool/klp-identity.h
@@ -14,6 +14,7 @@ struct identity {
const char *source; /* physical defining TU path, or "" */
const char *scope; /* slash-delimited enclosing scopes */
const char *demangled_name; /* suffix-stripped symbol name */
+ const char *path; /* source/scope/demangled_name */
bool external;
};
diff --git a/tools/objtool/include/objtool/klp.h b/tools/objtool/include/objtool/klp.h
index c57775d78c71..564890cd1d5f 100644
--- a/tools/objtool/include/objtool/klp.h
+++ b/tools/objtool/include/objtool/klp.h
@@ -51,6 +51,8 @@ struct objtool_file;
struct elf;
struct symbol;
+bool dont_correlate(struct symbol *sym);
+
int klp_create_symid_sections(struct objtool_file *file);
int klp_sympos_init(struct elf *orig);
diff --git a/tools/objtool/klp-checksum.c b/tools/objtool/klp-checksum.c
index 1f1b5f068168..54b89c3e6d1b 100644
--- a/tools/objtool/klp-checksum.c
+++ b/tools/objtool/klp-checksum.c
@@ -98,8 +98,8 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
__checksum_update_insn(func, insn, buf, len);
if (call_dest) {
- __checksum_update_insn(func, insn, call_dest->identity.demangled_name,
- strlen(call_dest->identity.demangled_name));
+ __checksum_update_insn(func, insn, call_dest->identity.path,
+ strlen(call_dest->identity.path));
} else if (jump_dest) {
struct symbol *dest_sym;
@@ -115,8 +115,8 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
if (!dest_sym)
goto alts;
- __checksum_update_insn(func, insn, dest_sym->identity.demangled_name,
- strlen(dest_sym->identity.demangled_name));
+ __checksum_update_insn(func, insn, dest_sym->identity.path,
+ strlen(dest_sym->identity.path));
offset = jump_dest->offset - dest_sym->offset;
__checksum_update_insn(func, insn, &offset, sizeof(offset));
@@ -158,8 +158,8 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
offset -= sym->offset;
}
- __checksum_update_insn(func, insn, sym->identity.demangled_name,
- strlen(sym->identity.demangled_name));
+ __checksum_update_insn(func, insn, sym->identity.path,
+ strlen(sym->identity.path));
__checksum_update_insn(func, insn, &offset, sizeof(offset));
alts:
@@ -227,9 +227,9 @@ static void checksum_update_object(struct objtool_file *file, struct symbol *sym
offset -= target->offset;
}
- __checksum_update_object(sym, sym_offset, "reloc name",
- target->identity.demangled_name,
- strlen(target->identity.demangled_name));
+ __checksum_update_object(sym, sym_offset, "reloc identity",
+ target->identity.path,
+ strlen(target->identity.path));
__checksum_update_object(sym, sym_offset, "reloc addend",
&offset, sizeof(offset));
}
@@ -325,6 +325,7 @@ static const char * const klp_checksum_usage[] = {
int cmd_klp_checksum(int argc, const char **argv)
{
struct objtool_file *file;
+ struct symbol *sym;
int ret;
const struct option options[] = {
@@ -349,6 +350,12 @@ int cmd_klp_checksum(int argc, const char **argv)
if (ret)
goto out;
+ for_each_sym(file->elf, sym)
+ sym->dont_correlate = dont_correlate(sym);
+ ret = prepare_identities(file->elf);
+ if (ret)
+ goto out;
+
ret = calculate_checksums(file);
if (ret)
goto out;
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 957e589b6603..b86886c41950 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -425,7 +425,7 @@ static bool is_metadata_section(struct section *sec)
* These symbols should never be correlated, so their local patched versions
* are used instead of linking to the originals.
*/
-static bool dont_correlate(struct symbol *sym)
+bool dont_correlate(struct symbol *sym)
{
return is_file_sym(sym) ||
is_null_sym(sym) ||
diff --git a/tools/objtool/klp-identity.c b/tools/objtool/klp-identity.c
index 627eda694389..ca8e65d5d392 100644
--- a/tools/objtool/klp-identity.c
+++ b/tools/objtool/klp-identity.c
@@ -156,12 +156,19 @@ int prepare_identities(struct elf *elf)
for_each_sym(elf, sym) {
struct identity *identity = &sym->identity;
+ char *path;
/* Default to STT_FILE and "/" for missing DWARF information. */
if (!identity->external && !*identity->source && sym->file)
identity->source = sym->file->identity.source;
if (!identity->scope)
identity->scope = "/";
+ if (asprintf(&path, "%s%s%s", identity->source, identity->scope,
+ identity->demangled_name) < 0) {
+ ERROR_GLIBC("asprintf");
+ return -1;
+ }
+ identity->path = path;
if (!sym->dont_correlate)
elf_hash_add(symbol_identity, &sym->identity_hash, identity_hash(identity));
}
--
2.53.0