diff options
author | Peter Zijlstra <peterz@infradead.org> | 2020-03-12 11:23:36 +0100 |
---|---|---|
committer | Peter Zijlstra <peterz@infradead.org> | 2020-03-25 18:28:30 +0100 |
commit | 8b5fa6bc326bf02f293b5a39a8f5b3de816265d3 (patch) | |
tree | 11121ed0c5015841e16a84207a1bf80a31f09dfb /tools/objtool/elf.h | |
parent | cdb3d057a17d56363a831e486ea39e4c389a6cf9 (diff) |
objtool: Optimize read_sections()
Perf showed that __hash_init() is a significant portion of
read_sections(), so instead of doing a per section rela_hash, use an
elf-wide rela_hash.
Statistics show us there are about 1.1 million relas, so size it
accordingly.
This reduces the objtool on vmlinux.o runtime to a third, from 15 to 5
seconds.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20200324160924.739153726@infradead.org
Diffstat (limited to 'tools/objtool/elf.h')
-rw-r--r-- | tools/objtool/elf.h | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h index 3088d925d640..dfd2431ef693 100644 --- a/tools/objtool/elf.h +++ b/tools/objtool/elf.h @@ -33,7 +33,6 @@ struct section { struct rb_root symbol_tree; struct list_head symbol_list; struct list_head rela_list; - DECLARE_HASHTABLE(rela_hash, 16); struct section *base, *rela; struct symbol *sym; Elf_Data *data; @@ -81,8 +80,22 @@ struct elf { DECLARE_HASHTABLE(symbol_name_hash, 20); DECLARE_HASHTABLE(section_hash, 16); DECLARE_HASHTABLE(section_name_hash, 16); + DECLARE_HASHTABLE(rela_hash, 20); }; +static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) +{ + u32 ol = offset, oh = offset >> 32, idx = sec->idx; + + __jhash_mix(ol, oh, idx); + + return ol; +} + +static inline u32 rela_hash(struct rela *rela) +{ + return sec_offset_hash(rela->sec, rela->offset); +} struct elf *elf_read(const char *name, int flags); struct section *find_section_by_name(struct elf *elf, const char *name); @@ -90,9 +103,9 @@ 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(struct elf *elf, const char *name); struct symbol *find_symbol_containing(struct section *sec, unsigned long offset); -struct rela *find_rela_by_dest(struct section *sec, unsigned long offset); -struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset, - unsigned int len); +struct rela *find_rela_by_dest(struct elf *elf, struct section *sec, unsigned long offset); +struct rela *find_rela_by_dest_range(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int len); struct symbol *find_func_containing(struct section *sec, unsigned long offset); struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr); |