[PATCH] objtool: Speed up SHT_GROUP reindexing

Josh Poimboeuf posted 1 patch 7 months, 1 week ago
There is a newer version of this series
tools/objtool/elf.c                 | 47 ++++++++++++++++++-----------
tools/objtool/include/objtool/elf.h |  1 +
2 files changed, 30 insertions(+), 18 deletions(-)
[PATCH] objtool: Speed up SHT_GROUP reindexing
Posted by Josh Poimboeuf 7 months, 1 week ago
From 2a33e583c87e3283706f346f9d59aac20653b7fd Mon Sep 17 00:00:00 2001
Message-ID: <2a33e583c87e3283706f346f9d59aac20653b7fd.1746662991.git.jpoimboe@kernel.org>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Date: Wed, 7 May 2025 16:56:55 -0700
Subject: [PATCH] objtool: Speed up SHT_GROUP reindexing

After elf_update_group_sh_info() was introduced, a prototype version of
"objtool klp diff" went from taking ~1s to several minutes, due to
looping almost endlessly in elf_update_group_sh_info() while creating
thousands of local symbols in a file with thousands of sections.

Dramatically improve the performance by marking all symbols' correlated
SHT_GROUP sections while reading the object.  That way there's no need
to search for it every time a symbol gets reindexed.

Fixes: 2cb291596e2c ("objtool: Fix up st_info in COMDAT group section")
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 47 ++++++++++++++++++-----------
 tools/objtool/include/objtool/elf.h |  1 +
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8dffe68d705c..ca5d77db692a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -572,28 +572,32 @@ static int read_symbols(struct elf *elf)
 	return -1;
 }
 
-/*
- * @sym's idx has changed.  Update the sh_info in group sections.
- */
-static void elf_update_group_sh_info(struct elf *elf, Elf32_Word symtab_idx,
-				     Elf32_Word new_idx, Elf32_Word old_idx)
+static int mark_group_syms(struct elf *elf)
 {
-	struct section *sec;
+	struct section *symtab, *sec;
+	struct symbol *sym;
+
+	symtab = find_section_by_name(elf, ".symtab");
+	if (!symtab) {
+		ERROR("no .symtab");
+		return -1;
+	}
 
 	list_for_each_entry(sec, &elf->sections, list) {
-		if (sec->sh.sh_type != SHT_GROUP)
-			continue;
-		if (sec->sh.sh_link == symtab_idx &&
-		    sec->sh.sh_info == old_idx) {
-			sec->sh.sh_info = new_idx;
-			mark_sec_changed(elf, sec, true);
-			/*
-			 * Each ELF group should have a unique symbol key.
-			 * Return early on match.
-			 */
-			return;
+		if (sec->sh.sh_type == SHT_GROUP &&
+		    sec->sh.sh_link == symtab->idx) {
+			sym = find_symbol_by_index(elf, sec->sh.sh_info);
+			if (!sym) {
+				ERROR("%s: can't find SHT_GROUP signature symbol",
+				      sec->name);
+				return -1;
+			}
+
+			sym->group_sec = sec;
 		}
 	}
+
+	return 0;
 }
 
 /*
@@ -787,7 +791,11 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 		if (elf_update_sym_relocs(elf, old))
 			return NULL;
 
-		elf_update_group_sh_info(elf, symtab->idx, new_idx, first_non_local);
+		if (old->group_sec) {
+			old->group_sec->sh.sh_info = new_idx;
+			mark_sec_changed(elf, old->group_sec, true);
+		}
+
 		new_idx = first_non_local;
 	}
 
@@ -1060,6 +1068,9 @@ struct elf *elf_open_read(const char *name, int flags)
 	if (read_symbols(elf))
 		goto err;
 
+	if (mark_group_syms(elf))
+		goto err;
+
 	if (read_relocs(elf))
 		goto err;
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index c7c4e87ebe88..0a2fa3ac0079 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -72,6 +72,7 @@ struct symbol {
 	u8 ignore	     : 1;
 	struct list_head pv_target;
 	struct reloc *relocs;
+	struct section *group_sec;
 };
 
 struct reloc {
-- 
2.49.0
Re: [PATCH] objtool: Speed up SHT_GROUP reindexing
Posted by Josh Poimboeuf 7 months, 1 week ago
On Wed, May 07, 2025 at 05:11:03PM -0700, Josh Poimboeuf wrote:
> From 2a33e583c87e3283706f346f9d59aac20653b7fd Mon Sep 17 00:00:00 2001
> Message-ID: <2a33e583c87e3283706f346f9d59aac20653b7fd.1746662991.git.jpoimboe@kernel.org>
> From: Josh Poimboeuf <jpoimboe@kernel.org>
> Date: Wed, 7 May 2025 16:56:55 -0700
> Subject: [PATCH] objtool: Speed up SHT_GROUP reindexing

Urgh, sorry about the patch formatting, the above can obviously be
dropped.

-- 
Josh
Re: [PATCH] objtool: Speed up SHT_GROUP reindexing
Posted by Peter Zijlstra 7 months, 1 week ago
On Wed, May 07, 2025 at 05:11:53PM -0700, Josh Poimboeuf wrote:
> On Wed, May 07, 2025 at 05:11:03PM -0700, Josh Poimboeuf wrote:
> > From 2a33e583c87e3283706f346f9d59aac20653b7fd Mon Sep 17 00:00:00 2001
> > Message-ID: <2a33e583c87e3283706f346f9d59aac20653b7fd.1746662991.git.jpoimboe@kernel.org>
> > From: Josh Poimboeuf <jpoimboe@kernel.org>
> > Date: Wed, 7 May 2025 16:56:55 -0700
> > Subject: [PATCH] objtool: Speed up SHT_GROUP reindexing
> 
> Urgh, sorry about the patch formatting, the above can obviously be
> dropped.

No worries, my script did it almost right :-)

Patch seems sane to me; I'll go stick it into objtool/core. Rong if you
could verify your case still work correctly that would be appreciated.
Re: [PATCH] objtool: Speed up SHT_GROUP reindexing
Posted by Rong Xu 7 months, 1 week ago
On Thu, May 8, 2025 at 8:27 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Wed, May 07, 2025 at 05:11:53PM -0700, Josh Poimboeuf wrote:
> > On Wed, May 07, 2025 at 05:11:03PM -0700, Josh Poimboeuf wrote:
> > > From 2a33e583c87e3283706f346f9d59aac20653b7fd Mon Sep 17 00:00:00 2001
> > > Message-ID: <2a33e583c87e3283706f346f9d59aac20653b7fd.1746662991.git.jpoimboe@kernel.org>
> > > From: Josh Poimboeuf <jpoimboe@kernel.org>
> > > Date: Wed, 7 May 2025 16:56:55 -0700
> > > Subject: [PATCH] objtool: Speed up SHT_GROUP reindexing
> >
> > Urgh, sorry about the patch formatting, the above can obviously be
> > dropped.
>
> No worries, my script did it almost right :-)
>
> Patch seems sane to me; I'll go stick it into objtool/core. Rong if you
> could verify your case still work correctly that would be appreciated.

I tested the patch, and it works for me.

I also looked at the patch. It assumes there is only one .symtab section.
 In general, there can be multiple symtab sections in an ELF file. But this
(i.e. one symtab) most likely holds for the kernel.

Tested-by: Rong Xu <xur@google.com>

Thanks,

-Rong

>