mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-06-21 15:43:21 +02:00
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:
+17
-51
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user