objtool: Replace iterator callback with for_each_sym_by_mangled_name()

Convert the callback-based iterate_sym_by_demangled_name() with a new
for_each_sym_by_demangled_name() macro.  This eliminates the callback
struct/function and makes the code more compact and readable.

Acked-by: Song Liu <song@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
Josh Poimboeuf
2026-04-12 22:41:23 -07:00
parent 3de711fba7
commit 0333b73995
3 changed files with 60 additions and 82 deletions
+17 -51
View File
@@ -27,27 +27,16 @@
static ssize_t demangled_name_len(const char *name);
static inline u32 str_hash(const char *str)
{
return jhash(str, strlen(str), 0);
}
static inline u32 str_hash_demangled(const char *str)
u32 str_hash_demangled(const char *str)
{
return jhash(str, demangled_name_len(str), 0);
}
#define __elf_table(name) (elf->name##_hash)
#define __elf_bits(name) (elf->name##_bits)
#define __elf_table_entry(name, key) \
__elf_table(name)[hash_min(key, __elf_bits(name))]
#define elf_hash_add(name, node, key) \
({ \
struct elf_hash_node *__node = node; \
__node->next = __elf_table_entry(name, key); \
__elf_table_entry(name, key) = __node; \
__node->next = __elf_table_entry(elf, name, key); \
__elf_table_entry(elf, name, key) = __node; \
})
static inline void __elf_hash_del(struct elf_hash_node *node,
@@ -69,30 +58,20 @@ static inline void __elf_hash_del(struct elf_hash_node *node,
}
#define elf_hash_del(name, node, key) \
__elf_hash_del(node, &__elf_table_entry(name, key))
#define elf_list_entry(ptr, type, member) \
({ \
typeof(ptr) __ptr = (ptr); \
__ptr ? container_of(__ptr, type, member) : NULL; \
})
#define elf_hash_for_each_possible(name, obj, member, key) \
for (obj = elf_list_entry(__elf_table_entry(name, key), typeof(*obj), member); \
obj; \
obj = elf_list_entry(obj->member.next, typeof(*(obj)), member))
__elf_hash_del(node, &__elf_table_entry(elf, name, key))
#define elf_alloc_hash(name, size) \
({ \
__elf_bits(name) = max(10, ilog2(size)); \
__elf_table(name) = mmap(NULL, sizeof(struct elf_hash_node *) << __elf_bits(name), \
__elf_bits(elf, name) = max(10, ilog2(size)); \
__elf_table(elf, name) = mmap(NULL, \
sizeof(struct elf_hash_node *) << __elf_bits(elf, name), \
PROT_READ|PROT_WRITE, \
MAP_PRIVATE|MAP_ANON, -1, 0); \
if (__elf_table(name) == (void *)-1L) { \
if (__elf_table(elf, name) == (void *)-1L) { \
ERROR_GLIBC("mmap fail " #name); \
__elf_table(name) = NULL; \
__elf_table(elf, name) = NULL; \
} \
__elf_table(name); \
__elf_table(elf, name); \
})
static inline unsigned long __sym_start(struct symbol *s)
@@ -141,7 +120,7 @@ struct section *find_section_by_name(const struct elf *elf, const char *name)
{
struct section *sec;
elf_hash_for_each_possible(section_name, sec, name_hash, str_hash(name)) {
elf_hash_for_each_possible(elf, section_name, sec, name_hash, str_hash(name)) {
if (!strcmp(sec->name, name))
return sec;
}
@@ -154,7 +133,7 @@ static struct section *find_section_by_index(struct elf *elf,
{
struct section *sec;
elf_hash_for_each_possible(section, sec, hash, idx) {
elf_hash_for_each_possible(elf, section, sec, hash, idx) {
if (sec->idx == idx)
return sec;
}
@@ -166,7 +145,7 @@ static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
{
struct symbol *sym;
elf_hash_for_each_possible(symbol, sym, hash, idx) {
elf_hash_for_each_possible(elf, symbol, sym, hash, idx) {
if (sym->idx == idx)
return sym;
}
@@ -285,7 +264,7 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
{
struct symbol *sym;
elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
elf_hash_for_each_possible(elf, symbol_name, sym, name_hash, str_hash(name)) {
if (!strcmp(sym->name, name))
return sym;
}
@@ -300,7 +279,7 @@ static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf,
{
struct symbol *sym;
elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
elf_hash_for_each_possible(elf, symbol_name, sym, name_hash, str_hash_demangled(name)) {
if (sym->bind == STB_LOCAL && sym->file == file &&
!strcmp(sym->name, name)) {
return sym;
@@ -314,7 +293,7 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
{
struct symbol *sym;
elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
elf_hash_for_each_possible(elf, symbol_name, sym, name_hash, str_hash_demangled(name)) {
if (!strcmp(sym->name, name) && !is_local_sym(sym))
return sym;
}
@@ -322,19 +301,6 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
return NULL;
}
void iterate_global_symbol_by_demangled_name(const struct elf *elf,
const char *demangled_name,
void (*process)(struct symbol *sym, void *data),
void *data)
{
struct symbol *sym;
elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(demangled_name)) {
if (!strcmp(sym->demangled_name, demangled_name) && !is_local_sym(sym))
process(sym, data);
}
}
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len)
{
@@ -347,7 +313,7 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
return NULL;
for_offset_range(o, offset, offset + len) {
elf_hash_for_each_possible(reloc, reloc, hash,
elf_hash_for_each_possible(elf, reloc, reloc, hash,
sec_offset_hash(rsec, o)) {
if (reloc->sec != rsec)
continue;
+29 -3
View File
@@ -21,6 +21,13 @@
#define SEC_NAME_LEN 1024
#define SYM_NAME_LEN 512
static inline u32 str_hash(const char *str)
{
return jhash(str, strlen(str), 0);
}
u32 str_hash_demangled(const char *str);
#define bswap_if_needed(elf, val) __bswap_if_needed(&elf->ehdr, val)
#ifdef LIBELF_USE_DEPRECATED
@@ -130,6 +137,23 @@ struct elf {
struct symbol *symbol_data;
};
#define __elf_table(elf, name) ((elf)->name##_hash)
#define __elf_bits(elf, name) ((elf)->name##_bits)
#define __elf_table_entry(elf, name, key) \
__elf_table(elf, name)[hash_min(key, __elf_bits(elf, name))]
#define elf_list_entry(ptr, type, member) \
({ \
typeof(ptr) __ptr = (ptr); \
__ptr ? container_of(__ptr, type, member) : NULL; \
})
#define elf_hash_for_each_possible(elf, name, obj, member, key) \
for (obj = elf_list_entry(__elf_table_entry(elf, name, key), typeof(*obj), member); \
obj; \
obj = elf_list_entry(obj->member.next, typeof(*(obj)), member))
struct elf *elf_open_read(const char *name, int flags);
struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name);
@@ -186,9 +210,6 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name);
void iterate_global_symbol_by_demangled_name(const struct elf *elf, const char *demangled_name,
void (*process)(struct symbol *sym, void *data),
void *data);
struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
@@ -468,6 +489,11 @@ static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next)
#define for_each_sym_continue(elf, sym) \
list_for_each_entry_continue(sym, &elf->symbols, global_list)
#define for_each_sym_by_demangled_name(elf, name, sym) \
elf_hash_for_each_possible(elf, symbol_name, sym, name_hash, \
str_hash(name)) \
if (strcmp(sym->demangled_name, name)) {} else
#define rsec_next_reloc(rsec, reloc) \
reloc_idx(reloc) < sec_num_entries(rsec) - 1 ? reloc + 1 : NULL
+14 -28
View File
@@ -46,11 +46,6 @@ static const struct option klp_diff_options[] = {
static DEFINE_HASHTABLE(exports, 15);
static inline u32 str_hash(const char *str)
{
return jhash(str, strlen(str), 0);
}
static char *escape_str(const char *orig)
{
size_t len = 0;
@@ -396,22 +391,6 @@ static bool dont_correlate(struct symbol *sym)
is_special_section_aux(sym->sec);
}
struct process_demangled_name_data {
struct symbol *ret;
int count;
};
static void process_demangled_name(struct symbol *sym, void *d)
{
struct process_demangled_name_data *data = d;
if (sym->twin)
return;
data->count++;
data->ret = sym;
}
/*
* When there is no full name match, try match demangled_name. This would
* match original foo.llvm.123 to patched foo.llvm.456.
@@ -423,16 +402,23 @@ static void process_demangled_name(struct symbol *sym, void *d)
static int find_global_symbol_by_demangled_name(struct elf *elf, struct symbol *sym,
struct symbol **out_sym)
{
struct process_demangled_name_data data = {};
struct symbol *sym2, *result = NULL;
int count = 0;
iterate_global_symbol_by_demangled_name(elf, sym->demangled_name,
process_demangled_name,
&data);
if (data.count > 1) {
ERROR("Multiple (%d) correlation candidates for %s", data.count, sym->name);
for_each_sym_by_demangled_name(elf, sym->demangled_name, sym2) {
if (is_local_sym(sym2) || sym2->twin)
continue;
count++;
result = sym2;
}
if (count > 1) {
ERROR("Multiple (%d) correlation candidates for %s", count, sym->name);
return -1;
}
*out_sym = data.ret;
*out_sym = result;
return 0;
}