Commit 65fb11a7 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

objtool: Optimize find_symbol_by_index()



The symbol index is object wide, not per section, so it makes no sense
to have the symbol_hash be part of the section object. By moving it to
the elf object we avoid the linear sections iteration.

This reduces the runtime of objtool on vmlinux.o from over 3 hours (I
gave up) to a few minutes. The defconfig vmlinux.o has around 20k
sections.

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarMiroslav Benes <mbenes@suse.cz>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20200324160924.261852348@infradead.org
parent 36cc5520
Loading
Loading
Loading
Loading
+5 −8
Original line number Original line Diff line number Diff line
@@ -46,11 +46,9 @@ static struct section *find_section_by_index(struct elf *elf,


static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
{
{
	struct section *sec;
	struct symbol *sym;
	struct symbol *sym;


	list_for_each_entry(sec, &elf->sections, list)
	hash_for_each_possible(elf->symbol_hash, sym, hash, idx)
		hash_for_each_possible(sec->symbol_hash, sym, hash, idx)
		if (sym->idx == idx)
		if (sym->idx == idx)
			return sym;
			return sym;


@@ -166,7 +164,6 @@ static int read_sections(struct elf *elf)
		INIT_LIST_HEAD(&sec->symbol_list);
		INIT_LIST_HEAD(&sec->symbol_list);
		INIT_LIST_HEAD(&sec->rela_list);
		INIT_LIST_HEAD(&sec->rela_list);
		hash_init(sec->rela_hash);
		hash_init(sec->rela_hash);
		hash_init(sec->symbol_hash);


		list_add_tail(&sec->list, &elf->sections);
		list_add_tail(&sec->list, &elf->sections);


@@ -299,7 +296,7 @@ static int read_symbols(struct elf *elf)
		}
		}
		sym->alias = alias;
		sym->alias = alias;
		list_add(&sym->list, entry);
		list_add(&sym->list, entry);
		hash_add(sym->sec->symbol_hash, &sym->hash, sym->idx);
		hash_add(elf->symbol_hash, &sym->hash, sym->idx);
	}
	}


	/* Create parent/child links for any cold subfunctions */
	/* Create parent/child links for any cold subfunctions */
@@ -425,6 +422,7 @@ struct elf *elf_read(const char *name, int flags)
	}
	}
	memset(elf, 0, sizeof(*elf));
	memset(elf, 0, sizeof(*elf));


	hash_init(elf->symbol_hash);
	INIT_LIST_HEAD(&elf->sections);
	INIT_LIST_HEAD(&elf->sections);


	elf->fd = open(name, flags);
	elf->fd = open(name, flags);
@@ -486,7 +484,6 @@ struct section *elf_create_section(struct elf *elf, const char *name,
	INIT_LIST_HEAD(&sec->symbol_list);
	INIT_LIST_HEAD(&sec->symbol_list);
	INIT_LIST_HEAD(&sec->rela_list);
	INIT_LIST_HEAD(&sec->rela_list);
	hash_init(sec->rela_hash);
	hash_init(sec->rela_hash);
	hash_init(sec->symbol_hash);


	list_add_tail(&sec->list, &elf->sections);
	list_add_tail(&sec->list, &elf->sections);


+1 −2
Original line number Original line Diff line number Diff line
@@ -27,7 +27,6 @@ struct section {
	struct list_head list;
	struct list_head list;
	GElf_Shdr sh;
	GElf_Shdr sh;
	struct list_head symbol_list;
	struct list_head symbol_list;
	DECLARE_HASHTABLE(symbol_hash, 8);
	struct list_head rela_list;
	struct list_head rela_list;
	DECLARE_HASHTABLE(rela_hash, 16);
	DECLARE_HASHTABLE(rela_hash, 16);
	struct section *base, *rela;
	struct section *base, *rela;
@@ -71,7 +70,7 @@ struct elf {
	int fd;
	int fd;
	char *name;
	char *name;
	struct list_head sections;
	struct list_head sections;
	DECLARE_HASHTABLE(rela_hash, 16);
	DECLARE_HASHTABLE(symbol_hash, 20);
};
};