diff options
| author | Josh Poimboeuf <jpoimboe@kernel.org> | 2025-09-17 09:03:57 -0700 |
|---|---|---|
| committer | Josh Poimboeuf <jpoimboe@kernel.org> | 2025-10-14 14:50:17 -0700 |
| commit | 0d83da43b1e1c8ce19f2bb10f54a0fdf795364f7 (patch) | |
| tree | 2f2ef8f8f2d52d7e02d0ac32c650d97afc8c2cad /tools/objtool/elf.c | |
| parent | f6b740ef5f4724f95363ac0d664e88d221343fa1 (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.c | 46 |
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; } |
