summaryrefslogtreecommitdiff
path: root/tools/objtool/elf.c
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@kernel.org>2025-09-17 09:03:57 -0700
committerJosh Poimboeuf <jpoimboe@kernel.org>2025-10-14 14:50:17 -0700
commit0d83da43b1e1c8ce19f2bb10f54a0fdf795364f7 (patch)
tree2f2ef8f8f2d52d7e02d0ac32c650d97afc8c2cad /tools/objtool/elf.c
parentf6b740ef5f4724f95363ac0d664e88d221343fa1 (diff)
objtool/klp: Add --checksum option to generate per-function checksums
In preparation for the objtool klp diff subcommand, add a command-line option to generate a unique checksum for each function. This will enable detection of functions which have changed between two versions of an object file. Acked-by: Petr Mladek <pmladek@suse.com> Tested-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Diffstat (limited to 'tools/objtool/elf.c')
-rw-r--r--tools/objtool/elf.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6095baba8e9c..0119b3b4c554 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -17,6 +17,7 @@
#include <unistd.h>
#include <errno.h>
#include <libgen.h>
+#include <ctype.h>
#include <linux/interval_tree_generic.h>
#include <objtool/builtin.h>
#include <objtool/elf.h>
@@ -412,7 +413,38 @@ static int read_sections(struct elf *elf)
return 0;
}
-static void elf_add_symbol(struct elf *elf, struct symbol *sym)
+static const char *demangle_name(struct symbol *sym)
+{
+ char *str;
+
+ if (!is_local_sym(sym))
+ return sym->name;
+
+ if (!is_func_sym(sym) && !is_object_sym(sym))
+ return sym->name;
+
+ if (!strstarts(sym->name, "__UNIQUE_ID_") && !strchr(sym->name, '.'))
+ return sym->name;
+
+ str = strdup(sym->name);
+ if (!str) {
+ ERROR_GLIBC("strdup");
+ return NULL;
+ }
+
+ for (int i = strlen(str) - 1; i >= 0; i--) {
+ char c = str[i];
+
+ if (!isdigit(c) && c != '.') {
+ str[i + 1] = '\0';
+ break;
+ }
+ };
+
+ return str;
+}
+
+static int elf_add_symbol(struct elf *elf, struct symbol *sym)
{
struct list_head *entry;
struct rb_node *pnode;
@@ -456,6 +488,12 @@ static void elf_add_symbol(struct elf *elf, struct symbol *sym)
if (is_func_sym(sym) && strstr(sym->name, ".cold"))
sym->cold = 1;
sym->pfunc = sym->cfunc = sym;
+
+ sym->demangled_name = demangle_name(sym);
+ if (!sym->demangled_name)
+ return -1;
+
+ return 0;
}
static int read_symbols(struct elf *elf)
@@ -529,7 +567,8 @@ static int read_symbols(struct elf *elf)
} else
sym->sec = find_section_by_index(elf, 0);
- elf_add_symbol(elf, sym);
+ if (elf_add_symbol(elf, sym))
+ return -1;
}
if (opts.stats) {
@@ -867,7 +906,8 @@ non_local:
mark_sec_changed(elf, symtab_shndx, true);
}
- elf_add_symbol(elf, sym);
+ if (elf_add_symbol(elf, sym))
+ return NULL;
return sym;
}