All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO
@ 2023-05-30 17:20 Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 01/22] objtool: Tidy elf.h Josh Poimboeuf
                   ` (21 more replies)
  0 siblings, 22 replies; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

DWARF uses a LOT of relocations, causing objtool to need a LOT of memory
for processing vmlinux.o.

In the worst case of an allyesconfig+CONFIG_DEBUG_INFO kernel, DWARF
creates almost 200 million relocations, ballooning objtool's peak heap
usage to 53GB.  These patches reduce that to 25GB.

On a distro-type kernel with kernel IBT enabled, they reduce objtool's
peak heap usage from 4.2GB to 2.8GB.

They also improve the runtime significantly (from 2m50s to 1m54s on my
system with allyesconfig+CONFIG_DEBUG_INFO), though most of that comes
from fixing the size calculation for reloc_hash.

Josh Poimboeuf (22):
  objtool: Tidy elf.h
  objtool: Remove flags argument from elf_create_section()
  objtool: Improve reloc naming
  objtool: Consolidate rel/rela handling
  objtool: Fix reloc_hash size
  objtool: Add mark_sec_changed()
  objtool: Add elf_create_section_pair()
  objtool: Keep GElf_Rel[a] structs synced
  objtool: Don't free memory in elf_close()
  objtool: Add for_each_reloc()
  objtool: Allocate relocs in advance for new rela sections
  objtool: Get rid of reloc->list
  objtool: Get rid of reloc->idx
  objtool: Get rid of reloc->offset
  objtool: Get rid of reloc->type
  objtool: Get rid of reloc->addend
  objtool: Get rid of reloc->jump_table_start
  objtool: Shrink reloc->sym_reloc_entry
  objtool: Shrink elf hash nodes
  objtool: Get rid of reloc->rel[a]
  objtool: Free insns when done
  objtool: Skip reading DWARF section data

 tools/objtool/arch/powerpc/include/arch/elf.h |  11 +-
 tools/objtool/arch/x86/decode.c               |   6 +-
 tools/objtool/arch/x86/include/arch/elf.h     |  11 +-
 tools/objtool/arch/x86/special.c              |   6 +-
 tools/objtool/check.c                         | 429 +++++++-------
 tools/objtool/elf.c                           | 537 +++++++-----------
 tools/objtool/include/objtool/elf.h           | 326 ++++++++---
 tools/objtool/orc_gen.c                       |   8 +-
 tools/objtool/special.c                       |   4 +-
 9 files changed, 698 insertions(+), 640 deletions(-)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH 01/22] objtool: Tidy elf.h
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 02/22] objtool: Remove flags argument from elf_create_section() Josh Poimboeuf
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Reorganize elf.h a bit:

- Move the prototypes higher up so they can be used by the inline
  functions.

- Move hash-related code to the bottom.

- Remove the unused ELF_HASH_BITS macro.

No functional changes.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/include/objtool/elf.h | 96 ++++++++++++++---------------
 1 file changed, 47 insertions(+), 49 deletions(-)

diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 78e2d0fc21ca..b24f83e7ca34 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -83,8 +83,6 @@ struct reloc {
 	bool jump_table_start;
 };
 
-#define ELF_HASH_BITS	20
-
 struct elf {
 	Elf *elf;
 	GElf_Ehdr ehdr;
@@ -110,53 +108,6 @@ struct elf {
 	struct symbol *symbol_data;
 };
 
-#define OFFSET_STRIDE_BITS	4
-#define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
-#define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))
-
-#define for_offset_range(_offset, _start, _end)			\
-	for (_offset = ((_start) & OFFSET_STRIDE_MASK);		\
-	     _offset >= ((_start) & OFFSET_STRIDE_MASK) &&	\
-	     _offset <= ((_end) & OFFSET_STRIDE_MASK);		\
-	     _offset += OFFSET_STRIDE)
-
-static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
-{
-	u32 ol, oh, idx = sec->idx;
-
-	offset &= OFFSET_STRIDE_MASK;
-
-	ol = offset;
-	oh = (offset >> 16) >> 16;
-
-	__jhash_mix(ol, oh, idx);
-
-	return ol;
-}
-
-static inline u32 reloc_hash(struct reloc *reloc)
-{
-	return sec_offset_hash(reloc->sec, reloc->offset);
-}
-
-/*
- * Try to see if it's a whole archive (vmlinux.o or module).
- *
- * Note this will miss the case where a module only has one source file.
- */
-static inline bool has_multiple_files(struct elf *elf)
-{
-	return elf->num_files > 1;
-}
-
-static inline int elf_class_addrsize(struct elf *elf)
-{
-	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
-		return sizeof(u32);
-	else
-		return sizeof(u64);
-}
-
 struct elf *elf_open_read(const char *name, int flags);
 struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
 
@@ -186,6 +137,24 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 				     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
 
+/*
+ * Try to see if it's a whole archive (vmlinux.o or module).
+ *
+ * Note this will miss the case where a module only has one source file.
+ */
+static inline bool has_multiple_files(struct elf *elf)
+{
+	return elf->num_files > 1;
+}
+
+static inline int elf_class_addrsize(struct elf *elf)
+{
+	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+		return sizeof(u32);
+	else
+		return sizeof(u64);
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -198,4 +167,33 @@ struct symbol *find_func_containing(struct section *sec, unsigned long offset);
 		for_each_sec(file, __sec)				\
 			sec_for_each_sym(__sec, sym)
 
+#define OFFSET_STRIDE_BITS	4
+#define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
+#define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))
+
+#define for_offset_range(_offset, _start, _end)			\
+	for (_offset = ((_start) & OFFSET_STRIDE_MASK);		\
+	     _offset >= ((_start) & OFFSET_STRIDE_MASK) &&	\
+	     _offset <= ((_end) & OFFSET_STRIDE_MASK);		\
+	     _offset += OFFSET_STRIDE)
+
+static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
+{
+	u32 ol, oh, idx = sec->idx;
+
+	offset &= OFFSET_STRIDE_MASK;
+
+	ol = offset;
+	oh = (offset >> 16) >> 16;
+
+	__jhash_mix(ol, oh, idx);
+
+	return ol;
+}
+
+static inline u32 reloc_hash(struct reloc *reloc)
+{
+	return sec_offset_hash(reloc->sec, reloc->offset);
+}
+
 #endif /* _OBJTOOL_ELF_H */
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 02/22] objtool: Remove flags argument from elf_create_section()
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 01/22] objtool: Tidy elf.h Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 03/22] objtool: Improve reloc naming Josh Poimboeuf
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Simplify the elf_create_section() interface a bit by removing the flags
argument.  Most callers don't care about changing the section header
flags.  If needed, they can be modified afterwards, just like any other
section header field.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 17 ++++++++++-------
 tools/objtool/elf.c                 | 10 +++++-----
 tools/objtool/include/objtool/elf.h |  2 +-
 tools/objtool/orc_gen.c             |  4 ++--
 4 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index a13c257f80dd..bc6771550423 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -676,11 +676,14 @@ static int create_static_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->static_call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE,
+	sec = elf_create_section(file->elf, ".static_call_sites",
 				 sizeof(struct static_call_site), idx);
 	if (!sec)
 		return -1;
 
+	/* Allow modules to set the low bits of static_call_site::key */
+	sec->sh.sh_flags |= SHF_WRITE;
+
 	idx = 0;
 	list_for_each_entry(insn, &file->static_call_list, call_node) {
 
@@ -762,7 +765,7 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".retpoline_sites", 0,
+	sec = elf_create_section(file->elf, ".retpoline_sites",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .retpoline_sites");
@@ -808,7 +811,7 @@ static int create_return_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".return_sites", 0,
+	sec = elf_create_section(file->elf, ".return_sites",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .return_sites");
@@ -860,7 +863,7 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".ibt_endbr_seal", 0,
+	sec = elf_create_section(file->elf, ".ibt_endbr_seal",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .ibt_endbr_seal");
@@ -919,7 +922,7 @@ static int create_cfi_sections(struct objtool_file *file)
 		idx++;
 	}
 
-	sec = elf_create_section(file->elf, ".cfi_sites", 0, sizeof(unsigned int), idx);
+	sec = elf_create_section(file->elf, ".cfi_sites", sizeof(unsigned int), idx);
 	if (!sec)
 		return -1;
 
@@ -967,7 +970,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", 0, addrsize, idx);
+	sec = elf_create_section(file->elf, "__mcount_loc", addrsize, idx);
 	if (!sec)
 		return -1;
 
@@ -1012,7 +1015,7 @@ static int create_direct_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".call_sites", 0, sizeof(unsigned int), idx);
+	sec = elf_create_section(file->elf, ".call_sites", sizeof(unsigned int), idx);
 	if (!sec)
 		return -1;
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 500e92979a31..7598c0a2633d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -1059,7 +1059,7 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 }
 
 struct section *elf_create_section(struct elf *elf, const char *name,
-				   unsigned int sh_flags, size_t entsize, int nr)
+				   size_t entsize, int nr)
 {
 	struct section *sec, *shstrtab;
 	size_t size = entsize * nr;
@@ -1117,7 +1117,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	sec->sh.sh_entsize = entsize;
 	sec->sh.sh_type = SHT_PROGBITS;
 	sec->sh.sh_addralign = 1;
-	sec->sh.sh_flags = SHF_ALLOC | sh_flags;
+	sec->sh.sh_flags = SHF_ALLOC;
 
 	/* Add section name to .shstrtab (or .strtab for Clang) */
 	shstrtab = find_section_by_name(elf, ".shstrtab");
@@ -1153,7 +1153,7 @@ static struct section *elf_create_rel_reloc_section(struct elf *elf, struct sect
 	strcpy(relocname, ".rel");
 	strcat(relocname, base->name);
 
-	sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rel), 0);
+	sec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
 	free(relocname);
 	if (!sec)
 		return NULL;
@@ -1185,9 +1185,9 @@ static struct section *elf_create_rela_reloc_section(struct elf *elf, struct sec
 	strcat(relocname, base->name);
 
 	if (addrsize == sizeof(u32))
-		sec = elf_create_section(elf, relocname, 0, sizeof(Elf32_Rela), 0);
+		sec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
 	else
-		sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rela), 0);
+		sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
 	free(relocname);
 	if (!sec)
 		return NULL;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index b24f83e7ca34..2c28aeeb3cb2 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -109,7 +109,7 @@ struct elf {
 };
 
 struct elf *elf_open_read(const char *name, int flags);
-struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
+struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
 
 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
 
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index 48efd1e2f00d..d5f750be7d7d 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -237,12 +237,12 @@ int orc_create(struct objtool_file *file)
 		WARN("file already has .orc_unwind section, skipping");
 		return -1;
 	}
-	orc_sec = elf_create_section(file->elf, ".orc_unwind", 0,
+	orc_sec = elf_create_section(file->elf, ".orc_unwind",
 				     sizeof(struct orc_entry), nr);
 	if (!orc_sec)
 		return -1;
 
-	sec = elf_create_section(file->elf, ".orc_unwind_ip", 0, sizeof(int), nr);
+	sec = elf_create_section(file->elf, ".orc_unwind_ip", sizeof(int), nr);
 	if (!sec)
 		return -1;
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 03/22] objtool: Improve reloc naming
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 01/22] objtool: Tidy elf.h Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 02/22] objtool: Remove flags argument from elf_create_section() Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 04/22] objtool: Consolidate rel/rela handling Josh Poimboeuf
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

- The term "reloc" is overloaded to mean both "an instance of struct
  reloc" and "a reloc section".  Change the latter to "rsec".

- For variable names, use "sec" for regular sections and "rsec" for rela
  sections to prevent them getting mixed up.

- For struct reloc variables, use "reloc" instead of "rel" everywhere
  for consistency.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 134 +++++++++++------------
 tools/objtool/elf.c                 | 164 ++++++++++++++--------------
 tools/objtool/include/objtool/elf.h |   2 +-
 3 files changed, 151 insertions(+), 149 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index bc6771550423..189b4161e713 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -493,7 +493,7 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 {
 	struct symbol *sym, *func;
 	unsigned long off, end;
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
 	sym = find_symbol_by_name(file->elf, symname);
@@ -503,19 +503,19 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 	off = sym->offset;
 	end = off + sym->len;
 	for (;;) {
-		rel = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
-		if (!rel)
+		reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
+		if (!reloc)
 			break;
 
-		func = rel->sym;
+		func = reloc->sym;
 		if (func->type == STT_SECTION)
-			func = find_symbol_by_offset(rel->sym->sec, rel->addend);
+			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
 
-		idx = (rel->offset - sym->offset) / sizeof(unsigned long);
+		idx = (reloc->offset - sym->offset) / sizeof(unsigned long);
 
 		objtool_pv_add(file, idx, func);
 
-		off = rel->offset + 1;
+		off = reloc->offset + 1;
 		if (off > end)
 			break;
 	}
@@ -580,20 +580,20 @@ static struct instruction *find_last_insn(struct objtool_file *file,
  */
 static int add_dead_ends(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
 
 	/*
 	 * Check for manually annotated dead ends.
 	 */
-	sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.unreachable");
+	if (!rsec)
 		goto reachable;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
@@ -622,13 +622,13 @@ static int add_dead_ends(struct objtool_file *file)
 	 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
 	 * not a dead end.
 	 */
-	sec = find_section_by_name(file->elf, ".rela.discard.reachable");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.reachable");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
@@ -1043,15 +1043,15 @@ static int create_direct_call_sections(struct objtool_file *file)
 static void add_ignores(struct objtool_file *file)
 {
 	struct instruction *insn;
-	struct section *sec;
+	struct section *rsec;
 	struct symbol *func;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
+	if (!rsec)
 		return;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		switch (reloc->sym->type) {
 		case STT_FUNC:
 			func = reloc->sym;
@@ -1064,7 +1064,8 @@ static void add_ignores(struct objtool_file *file)
 			break;
 
 		default:
-			WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
+			WARN("unexpected relocation symbol type in %s: %d",
+			     rsec->name, reloc->sym->type);
 			continue;
 		}
 
@@ -1283,17 +1284,17 @@ static void add_uaccess_safe(struct objtool_file *file)
  */
 static int add_ignore_alternatives(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2203,7 +2204,7 @@ static void set_func_state(struct cfi_state *state)
 static int read_unwind_hints(struct objtool_file *file)
 {
 	struct cfi_state cfi = init_cfi;
-	struct section *sec, *relocsec;
+	struct section *sec;
 	struct unwind_hint *hint;
 	struct instruction *insn;
 	struct reloc *reloc;
@@ -2213,8 +2214,7 @@ static int read_unwind_hints(struct objtool_file *file)
 	if (!sec)
 		return 0;
 
-	relocsec = sec->reloc;
-	if (!relocsec) {
+	if (!sec->rsec) {
 		WARN("missing .rela.discard.unwind_hints section");
 		return -1;
 	}
@@ -2289,15 +2289,15 @@ static int read_unwind_hints(struct objtool_file *file)
 
 static int read_noendbr_hints(struct objtool_file *file)
 {
-	struct section *sec;
 	struct instruction *insn;
+	struct section *rsec;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.noendbr");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.noendbr");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
@@ -2312,17 +2312,17 @@ static int read_noendbr_hints(struct objtool_file *file)
 
 static int read_retpoline_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2348,17 +2348,17 @@ static int read_retpoline_hints(struct objtool_file *file)
 
 static int read_instr_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.instr_end");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2371,13 +2371,13 @@ static int read_instr_hints(struct objtool_file *file)
 		insn->instr--;
 	}
 
-	sec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2395,17 +2395,17 @@ static int read_instr_hints(struct objtool_file *file)
 
 static int read_validate_unret_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2424,19 +2424,19 @@ static int read_validate_unret_hints(struct objtool_file *file)
 static int read_intra_function_calls(struct objtool_file *file)
 {
 	struct instruction *insn;
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		unsigned long dest_off;
 
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s",
-			     sec->name);
+			     rsec->name);
 			return -1;
 		}
 
@@ -3332,15 +3332,15 @@ static inline bool func_uaccess_safe(struct symbol *func)
 static inline const char *call_dest_name(struct instruction *insn)
 {
 	static char pvname[19];
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
 	if (insn_call_dest(insn))
 		return insn_call_dest(insn)->name;
 
-	rel = insn_reloc(NULL, insn);
-	if (rel && !strcmp(rel->sym->name, "pv_ops")) {
-		idx = (rel->addend / sizeof(void *));
+	reloc = insn_reloc(NULL, insn);
+	if (reloc && !strcmp(reloc->sym->name, "pv_ops")) {
+		idx = (reloc->addend / sizeof(void *));
 		snprintf(pvname, sizeof(pvname), "pv_ops[%d]", idx);
 		return pvname;
 	}
@@ -3351,14 +3351,14 @@ static inline const char *call_dest_name(struct instruction *insn)
 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
 {
 	struct symbol *target;
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
-	rel = insn_reloc(file, insn);
-	if (!rel || strcmp(rel->sym->name, "pv_ops"))
+	reloc = insn_reloc(file, insn);
+	if (!reloc || strcmp(reloc->sym->name, "pv_ops"))
 		return false;
 
-	idx = (arch_dest_reloc_offset(rel->addend) / sizeof(void *));
+	idx = (arch_dest_reloc_offset(reloc->addend) / sizeof(void *));
 
 	if (file->pv_ops[idx].clean)
 		return true;
@@ -4401,7 +4401,7 @@ static int validate_ibt(struct objtool_file *file)
 		if (sec->sh.sh_flags & SHF_EXECINSTR)
 			continue;
 
-		if (!sec->reloc)
+		if (!sec->rsec)
 			continue;
 
 		/*
@@ -4428,7 +4428,7 @@ static int validate_ibt(struct objtool_file *file)
 		    strstr(sec->name, "__patchable_function_entries"))
 			continue;
 
-		list_for_each_entry(reloc, &sec->reloc->reloc_list, list)
+		list_for_each_entry(reloc, &sec->rsec->reloc_list, list)
 			warnings += validate_ibt_data_reloc(file, reloc);
 	}
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7598c0a2633d..86ae62dfdba2 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -233,17 +233,17 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 				     unsigned long offset, unsigned int len)
 {
 	struct reloc *reloc, *r = NULL;
+	struct section *rsec;
 	unsigned long o;
 
-	if (!sec->reloc)
+	rsec = sec->rsec;
+	if (!rsec)
 		return NULL;
 
-	sec = sec->reloc;
-
 	for_offset_range(o, offset, offset + len) {
 		elf_hash_for_each_possible(reloc, reloc, hash,
-					   sec_offset_hash(sec, o)) {
-			if (reloc->sec != sec)
+					   sec_offset_hash(rsec, o)) {
+			if (reloc->sec != rsec)
 				continue;
 
 			if (reloc->offset >= offset && reloc->offset < offset + len) {
@@ -534,7 +534,7 @@ static int read_symbols(struct elf *elf)
 }
 
 static struct section *elf_create_reloc_section(struct elf *elf,
-						struct section *base,
+						struct section *sec,
 						int reltype);
 
 int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
@@ -542,7 +542,7 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 {
 	struct reloc *reloc;
 
-	if (!sec->reloc && !elf_create_reloc_section(elf, sec, SHT_RELA))
+	if (!sec->rsec && !elf_create_reloc_section(elf, sec, SHT_RELA))
 		return -1;
 
 	reloc = malloc(sizeof(*reloc));
@@ -552,18 +552,18 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 	}
 	memset(reloc, 0, sizeof(*reloc));
 
-	reloc->sec = sec->reloc;
+	reloc->sec = sec->rsec;
 	reloc->offset = offset;
 	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &sec->reloc->reloc_list);
+	list_add_tail(&reloc->list, &sec->rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
-	sec->reloc->sh.sh_size += sec->reloc->sh.sh_entsize;
-	sec->reloc->changed = true;
+	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
+	sec->rsec->changed = true;
 
 	return 0;
 }
@@ -865,9 +865,9 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 	return elf_add_reloc(elf, sec, offset, type, sym, addend);
 }
 
-static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_rel_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
 {
-	if (!gelf_getrel(sec->data, i, &reloc->rel)) {
+	if (!gelf_getrel(rsec->data, i, &reloc->rel)) {
 		WARN_ELF("gelf_getrel");
 		return -1;
 	}
@@ -878,9 +878,9 @@ static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsig
 	return 0;
 }
 
-static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_rela_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
 {
-	if (!gelf_getrela(sec->data, i, &reloc->rela)) {
+	if (!gelf_getrela(rsec->data, i, &reloc->rela)) {
 		WARN_ELF("gelf_getrela");
 		return -1;
 	}
@@ -894,7 +894,7 @@ static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsi
 static int read_relocs(struct elf *elf)
 {
 	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	unsigned int symndx;
 	struct symbol *sym;
@@ -903,51 +903,52 @@ static int read_relocs(struct elf *elf)
 	if (!elf_alloc_hash(reloc, elf->text_size / 16))
 		return -1;
 
-	list_for_each_entry(sec, &elf->sections, list) {
-		if ((sec->sh.sh_type != SHT_RELA) &&
-		    (sec->sh.sh_type != SHT_REL))
+	list_for_each_entry(rsec, &elf->sections, list) {
+		if ((rsec->sh.sh_type != SHT_RELA) &&
+		    (rsec->sh.sh_type != SHT_REL))
 			continue;
 
-		sec->base = find_section_by_index(elf, sec->sh.sh_info);
-		if (!sec->base) {
+		rsec->base = find_section_by_index(elf, rsec->sh.sh_info);
+		if (!rsec->base) {
 			WARN("can't find base section for reloc section %s",
-			     sec->name);
+			     rsec->name);
 			return -1;
 		}
 
-		sec->base->reloc = sec;
+		rsec->base->rsec = rsec;
 
 		nr_reloc = 0;
-		sec->reloc_data = calloc(sec->sh.sh_size / sec->sh.sh_entsize, sizeof(*reloc));
-		if (!sec->reloc_data) {
+		rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
+					  sizeof(*reloc));
+		if (!rsec->reloc_data) {
 			perror("calloc");
 			return -1;
 		}
-		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
-			reloc = &sec->reloc_data[i];
-			switch (sec->sh.sh_type) {
+		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
+			reloc = &rsec->reloc_data[i];
+			switch (rsec->sh.sh_type) {
 			case SHT_REL:
-				if (read_rel_reloc(sec, i, reloc, &symndx))
+				if (read_rel_reloc(rsec, i, reloc, &symndx))
 					return -1;
 				break;
 			case SHT_RELA:
-				if (read_rela_reloc(sec, i, reloc, &symndx))
+				if (read_rela_reloc(rsec, i, reloc, &symndx))
 					return -1;
 				break;
 			default: return -1;
 			}
 
-			reloc->sec = sec;
+			reloc->sec = rsec;
 			reloc->idx = i;
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
-				     symndx, sec->name);
+				     symndx, rsec->name);
 				return -1;
 			}
 
 			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-			list_add_tail(&reloc->list, &sec->reloc_list);
+			list_add_tail(&reloc->list, &rsec->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 			nr_reloc++;
@@ -1140,40 +1141,41 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	return sec;
 }
 
-static struct section *elf_create_rel_reloc_section(struct elf *elf, struct section *base)
+static struct section *elf_create_rel_reloc_section(struct elf *elf,
+						    struct section *sec)
 {
 	char *relocname;
-	struct section *sec;
+	struct section *rsec;
 
-	relocname = malloc(strlen(base->name) + strlen(".rel") + 1);
+	relocname = malloc(strlen(sec->name) + strlen(".rel") + 1);
 	if (!relocname) {
 		perror("malloc");
 		return NULL;
 	}
 	strcpy(relocname, ".rel");
-	strcat(relocname, base->name);
+	strcat(relocname, sec->name);
 
-	sec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
+	rsec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
 	free(relocname);
-	if (!sec)
+	if (!rsec)
 		return NULL;
 
-	base->reloc = sec;
-	sec->base = base;
+	sec->rsec = rsec;
+	rsec->base = sec;
 
-	sec->sh.sh_type = SHT_REL;
-	sec->sh.sh_addralign = 8;
-	sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	sec->sh.sh_info = base->idx;
-	sec->sh.sh_flags = SHF_INFO_LINK;
+	rsec->sh.sh_type = SHT_REL;
+	rsec->sh.sh_addralign = 8;
+	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
+	rsec->sh.sh_info = sec->idx;
+	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	return sec;
+	return rsec;
 }
 
 static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base)
 {
 	char *relocname;
-	struct section *sec;
+	struct section *rsec;
 	int addrsize = elf_class_addrsize(elf);
 
 	relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
@@ -1185,23 +1187,23 @@ static struct section *elf_create_rela_reloc_section(struct elf *elf, struct sec
 	strcat(relocname, base->name);
 
 	if (addrsize == sizeof(u32))
-		sec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
+		rsec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
 	else
-		sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
+		rsec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
 	free(relocname);
-	if (!sec)
+	if (!rsec)
 		return NULL;
 
-	base->reloc = sec;
-	sec->base = base;
+	base->rsec = rsec;
+	rsec->base = base;
 
-	sec->sh.sh_type = SHT_RELA;
-	sec->sh.sh_addralign = addrsize;
-	sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	sec->sh.sh_info = base->idx;
-	sec->sh.sh_flags = SHF_INFO_LINK;
+	rsec->sh.sh_type = SHT_RELA;
+	rsec->sh.sh_addralign = addrsize;
+	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
+	rsec->sh.sh_info = base->idx;
+	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	return sec;
+	return rsec;
 }
 
 static struct section *elf_create_reloc_section(struct elf *elf,
@@ -1215,28 +1217,28 @@ static struct section *elf_create_reloc_section(struct elf *elf,
 	}
 }
 
-static int elf_rebuild_rel_reloc_section(struct section *sec)
+static int elf_rebuild_rel_reloc_section(struct section *rsec)
 {
 	struct reloc *reloc;
 	int idx = 0;
 	void *buf;
 
 	/* Allocate a buffer for relocations */
-	buf = malloc(sec->sh.sh_size);
+	buf = malloc(rsec->sh.sh_size);
 	if (!buf) {
 		perror("malloc");
 		return -1;
 	}
 
-	sec->data->d_buf = buf;
-	sec->data->d_size = sec->sh.sh_size;
-	sec->data->d_type = ELF_T_REL;
+	rsec->data->d_buf = buf;
+	rsec->data->d_size = rsec->sh.sh_size;
+	rsec->data->d_type = ELF_T_REL;
 
 	idx = 0;
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rel(sec->data, idx, &reloc->rel)) {
+		if (!gelf_update_rel(rsec->data, idx, &reloc->rel)) {
 			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
@@ -1246,29 +1248,29 @@ static int elf_rebuild_rel_reloc_section(struct section *sec)
 	return 0;
 }
 
-static int elf_rebuild_rela_reloc_section(struct section *sec)
+static int elf_rebuild_rela_reloc_section(struct section *rsec)
 {
 	struct reloc *reloc;
 	int idx = 0;
 	void *buf;
 
 	/* Allocate a buffer for relocations with addends */
-	buf = malloc(sec->sh.sh_size);
+	buf = malloc(rsec->sh.sh_size);
 	if (!buf) {
 		perror("malloc");
 		return -1;
 	}
 
-	sec->data->d_buf = buf;
-	sec->data->d_size = sec->sh.sh_size;
-	sec->data->d_type = ELF_T_RELA;
+	rsec->data->d_buf = buf;
+	rsec->data->d_size = rsec->sh.sh_size;
+	rsec->data->d_type = ELF_T_RELA;
 
 	idx = 0;
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rela.r_offset = reloc->offset;
 		reloc->rela.r_addend = reloc->addend;
 		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rela(sec->data, idx, &reloc->rela)) {
+		if (!gelf_update_rela(rsec->data, idx, &reloc->rela)) {
 			WARN_ELF("gelf_update_rela");
 			return -1;
 		}
@@ -1278,11 +1280,11 @@ static int elf_rebuild_rela_reloc_section(struct section *sec)
 	return 0;
 }
 
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *sec)
+static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
-	switch (sec->sh.sh_type) {
-	case SHT_REL:  return elf_rebuild_rel_reloc_section(sec);
-	case SHT_RELA: return elf_rebuild_rela_reloc_section(sec);
+	switch (rsec->sh.sh_type) {
+	case SHT_REL:  return elf_rebuild_rel_reloc_section(rsec);
+	case SHT_RELA: return elf_rebuild_rela_reloc_section(rsec);
 	default:       return -1;
 	}
 }
@@ -1308,13 +1310,13 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 
 int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 {
-	struct section *sec = reloc->sec;
+	struct section *rsec = reloc->sec;
 
-	if (sec->sh.sh_type == SHT_REL) {
+	if (rsec->sh.sh_type == SHT_REL) {
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 		reloc->rel.r_offset = reloc->offset;
 
-		if (!gelf_update_rel(sec->data, reloc->idx, &reloc->rel)) {
+		if (!gelf_update_rel(rsec->data, reloc->idx, &reloc->rel)) {
 			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
@@ -1323,7 +1325,7 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 		reloc->rela.r_addend = reloc->addend;
 		reloc->rela.r_offset = reloc->offset;
 
-		if (!gelf_update_rela(sec->data, reloc->idx, &reloc->rela)) {
+		if (!gelf_update_rela(rsec->data, reloc->idx, &reloc->rela)) {
 			WARN_ELF("gelf_update_rela");
 			return -1;
 		}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2c28aeeb3cb2..a4e43a69f922 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -33,7 +33,7 @@ struct section {
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
 	struct list_head reloc_list;
-	struct section *base, *reloc;
+	struct section *base, *rsec;
 	struct symbol *sym;
 	Elf_Data *data;
 	char *name;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 04/22] objtool: Consolidate rel/rela handling
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (2 preceding siblings ...)
  2023-05-30 17:20 ` [PATCH 03/22] objtool: Improve reloc naming Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 05/22] objtool: Fix reloc_hash size Josh Poimboeuf
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

The GElf_Rel[a] structs have more similarities than differences.  It's
safe to hard-code the assumptions about their shared fields as they will
never change.  Consolidate their handling where possible, getting rid of
duplicated code.

Also, at least for now we only ever create rela sections, so simplify
the relocation creation code to be rela-only.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               |  12 +-
 tools/objtool/elf.c                 | 202 ++++++++--------------------
 tools/objtool/include/objtool/elf.h |  13 +-
 3 files changed, 68 insertions(+), 159 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 189b4161e713..b6d0cb24085b 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -951,7 +951,7 @@ static int create_cfi_sections(struct objtool_file *file)
 
 static int create_mcount_loc_sections(struct objtool_file *file)
 {
-	int addrsize = elf_class_addrsize(file->elf);
+	size_t addr_size = elf_addr_size(file->elf);
 	struct instruction *insn;
 	struct section *sec;
 	int idx;
@@ -970,25 +970,25 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", addrsize, idx);
+	sec = elf_create_section(file->elf, "__mcount_loc", addr_size, idx);
 	if (!sec)
 		return -1;
 
-	sec->sh.sh_addralign = addrsize;
+	sec->sh.sh_addralign = addr_size;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
 		void *loc;
 
 		loc = sec->data->d_buf + idx;
-		memset(loc, 0, addrsize);
+		memset(loc, 0, addr_size);
 
 		if (elf_add_reloc_to_insn(file->elf, sec, idx,
-					  addrsize == sizeof(u64) ? R_ABS64 : R_ABS32,
+					  addr_size == sizeof(u64) ? R_ABS64 : R_ABS32,
 					  insn->sec, insn->offset))
 			return -1;
 
-		idx += addrsize;
+		idx += addr_size;
 	}
 
 	return 0;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 86ae62dfdba2..4bbdd8e6df2c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -533,16 +533,15 @@ static int read_symbols(struct elf *elf)
 	return -1;
 }
 
-static struct section *elf_create_reloc_section(struct elf *elf,
-						struct section *sec,
-						int reltype);
+static struct section *elf_create_rela_section(struct elf *elf,
+					       struct section *sec);
 
 int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 		  unsigned int type, struct symbol *sym, s64 addend)
 {
 	struct reloc *reloc;
 
-	if (!sec->rsec && !elf_create_reloc_section(elf, sec, SHT_RELA))
+	if (!sec->rsec && !elf_create_rela_section(elf, sec))
 		return -1;
 
 	reloc = malloc(sizeof(*reloc));
@@ -865,29 +864,25 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 	return elf_add_reloc(elf, sec, offset, type, sym, addend);
 }
 
-static int read_rel_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 {
-	if (!gelf_getrel(rsec->data, i, &reloc->rel)) {
-		WARN_ELF("gelf_getrel");
-		return -1;
-	}
-	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
-	reloc->addend = 0;
-	reloc->offset = reloc->rel.r_offset;
-	*symndx = GELF_R_SYM(reloc->rel.r_info);
-	return 0;
-}
+	bool rela = rsec->sh.sh_type == SHT_RELA;
+	void *retp;
 
-static int read_rela_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
-{
-	if (!gelf_getrela(rsec->data, i, &reloc->rela)) {
+	if (rela)
+		retp = gelf_getrela(rsec->data, i, &reloc->rela);
+	else
+		retp = gelf_getrel(rsec->data, i, &reloc->rel);
+
+	if (!retp) {
 		WARN_ELF("gelf_getrela");
 		return -1;
 	}
-	reloc->type = GELF_R_TYPE(reloc->rela.r_info);
-	reloc->addend = reloc->rela.r_addend;
-	reloc->offset = reloc->rela.r_offset;
-	*symndx = GELF_R_SYM(reloc->rela.r_info);
+
+	reloc->offset = reloc->rel.r_offset;
+	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
+	reloc->addend = rela ? reloc->rela.r_addend : 0;
+
 	return 0;
 }
 
@@ -926,20 +921,13 @@ static int read_relocs(struct elf *elf)
 		}
 		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
 			reloc = &rsec->reloc_data[i];
-			switch (rsec->sh.sh_type) {
-			case SHT_REL:
-				if (read_rel_reloc(rsec, i, reloc, &symndx))
-					return -1;
-				break;
-			case SHT_RELA:
-				if (read_rela_reloc(rsec, i, reloc, &symndx))
-					return -1;
-				break;
-			default: return -1;
-			}
+
+			if (read_reloc(rsec, i, reloc))
+				return -1;
 
 			reloc->sec = rsec;
 			reloc->idx = i;
+			symndx = GELF_R_SYM(reloc->rel.r_info);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
@@ -1141,30 +1129,30 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	return sec;
 }
 
-static struct section *elf_create_rel_reloc_section(struct elf *elf,
-						    struct section *sec)
+static struct section *elf_create_rela_section(struct elf *elf,
+					       struct section *sec)
 {
-	char *relocname;
 	struct section *rsec;
+	char *rsec_name;
 
-	relocname = malloc(strlen(sec->name) + strlen(".rel") + 1);
-	if (!relocname) {
+	rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1);
+	if (!rsec_name) {
 		perror("malloc");
 		return NULL;
 	}
-	strcpy(relocname, ".rel");
-	strcat(relocname, sec->name);
+	strcpy(rsec_name, ".rela");
+	strcat(rsec_name, sec->name);
 
-	rsec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
-	free(relocname);
+	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), 0);
+	free(rsec_name);
 	if (!rsec)
 		return NULL;
 
 	sec->rsec = rsec;
 	rsec->base = sec;
 
-	rsec->sh.sh_type = SHT_REL;
-	rsec->sh.sh_addralign = 8;
+	rsec->sh.sh_type = SHT_RELA;
+	rsec->sh.sh_addralign = elf_addr_size(elf);
 	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
@@ -1172,55 +1160,11 @@ static struct section *elf_create_rel_reloc_section(struct elf *elf,
 	return rsec;
 }
 
-static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base)
-{
-	char *relocname;
-	struct section *rsec;
-	int addrsize = elf_class_addrsize(elf);
-
-	relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
-	if (!relocname) {
-		perror("malloc");
-		return NULL;
-	}
-	strcpy(relocname, ".rela");
-	strcat(relocname, base->name);
-
-	if (addrsize == sizeof(u32))
-		rsec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
-	else
-		rsec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
-	free(relocname);
-	if (!rsec)
-		return NULL;
-
-	base->rsec = rsec;
-	rsec->base = base;
-
-	rsec->sh.sh_type = SHT_RELA;
-	rsec->sh.sh_addralign = addrsize;
-	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	rsec->sh.sh_info = base->idx;
-	rsec->sh.sh_flags = SHF_INFO_LINK;
-
-	return rsec;
-}
-
-static struct section *elf_create_reloc_section(struct elf *elf,
-					 struct section *base,
-					 int reltype)
-{
-	switch (reltype) {
-	case SHT_REL:  return elf_create_rel_reloc_section(elf, base);
-	case SHT_RELA: return elf_create_rela_reloc_section(elf, base);
-	default:       return NULL;
-	}
-}
-
-static int elf_rebuild_rel_reloc_section(struct section *rsec)
+static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
+	bool rela = rsec->sh.sh_type == SHT_RELA;
 	struct reloc *reloc;
-	int idx = 0;
+	int idx = 0, ret;
 	void *buf;
 
 	/* Allocate a buffer for relocations */
@@ -1232,13 +1176,19 @@ static int elf_rebuild_rel_reloc_section(struct section *rsec)
 
 	rsec->data->d_buf = buf;
 	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = ELF_T_REL;
+	rsec->data->d_type = rela ? ELF_T_RELA : ELF_T_REL;
 
 	idx = 0;
 	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rel(rsec->data, idx, &reloc->rel)) {
+		if (rela) {
+			reloc->rela.r_addend = reloc->addend;
+			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
+		} else {
+			ret = gelf_update_rel(rsec->data, idx, &reloc->rel);
+		}
+		if (!ret) {
 			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
@@ -1248,47 +1198,6 @@ static int elf_rebuild_rel_reloc_section(struct section *rsec)
 	return 0;
 }
 
-static int elf_rebuild_rela_reloc_section(struct section *rsec)
-{
-	struct reloc *reloc;
-	int idx = 0;
-	void *buf;
-
-	/* Allocate a buffer for relocations with addends */
-	buf = malloc(rsec->sh.sh_size);
-	if (!buf) {
-		perror("malloc");
-		return -1;
-	}
-
-	rsec->data->d_buf = buf;
-	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = ELF_T_RELA;
-
-	idx = 0;
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
-		reloc->rela.r_offset = reloc->offset;
-		reloc->rela.r_addend = reloc->addend;
-		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rela(rsec->data, idx, &reloc->rela)) {
-			WARN_ELF("gelf_update_rela");
-			return -1;
-		}
-		idx++;
-	}
-
-	return 0;
-}
-
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
-{
-	switch (rsec->sh.sh_type) {
-	case SHT_REL:  return elf_rebuild_rel_reloc_section(rsec);
-	case SHT_RELA: return elf_rebuild_rela_reloc_section(rsec);
-	default:       return -1;
-	}
-}
-
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn)
@@ -1311,24 +1220,21 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 {
 	struct section *rsec = reloc->sec;
+	int ret;
 
-	if (rsec->sh.sh_type == SHT_REL) {
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		reloc->rel.r_offset = reloc->offset;
+	reloc->rel.r_offset = reloc->offset;
+	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 
-		if (!gelf_update_rel(rsec->data, reloc->idx, &reloc->rel)) {
-			WARN_ELF("gelf_update_rel");
-			return -1;
-		}
-	} else {
-		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
+	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
-		reloc->rela.r_offset = reloc->offset;
+		ret = gelf_update_rela(rsec->data, reloc->idx, &reloc->rela);
+	} else {
+		ret = gelf_update_rel(rsec->data, reloc->idx, &reloc->rel);
+	}
 
-		if (!gelf_update_rela(rsec->data, reloc->idx, &reloc->rela)) {
-			WARN_ELF("gelf_update_rela");
-			return -1;
-		}
+	if (!ret) {
+		WARN_ELF("gelf_update_rela");
+		return -1;
 	}
 
 	elf->changed = true;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a4e43a69f922..6f82f2515d6b 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -12,6 +12,7 @@
 #include <linux/hashtable.h>
 #include <linux/rbtree.h>
 #include <linux/jhash.h>
+#include <arch/elf.h>
 
 #ifdef LIBELF_USE_DEPRECATED
 # define elf_getshdrnum    elf_getshnum
@@ -147,12 +148,14 @@ static inline bool has_multiple_files(struct elf *elf)
 	return elf->num_files > 1;
 }
 
-static inline int elf_class_addrsize(struct elf *elf)
+static inline size_t elf_addr_size(struct elf *elf)
 {
-	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
-		return sizeof(u32);
-	else
-		return sizeof(u64);
+	return elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+}
+
+static inline size_t elf_rela_size(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
 #define for_each_sec(file, sec)						\
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 05/22] objtool: Fix reloc_hash size
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (3 preceding siblings ...)
  2023-05-30 17:20 ` [PATCH 04/22] objtool: Consolidate rel/rela handling Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 06/22] objtool: Add mark_sec_changed() Josh Poimboeuf
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

With CONFIG_DEBUG_INFO, DWARF creates a lot of relocations and
reloc_hash is woefully undersized, which can affect performance
significantly.  Fix that.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 16 +++++++---------
 tools/objtool/include/objtool/elf.h |  8 +++++++-
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4bbdd8e6df2c..f72ec6d8fb14 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -328,12 +328,12 @@ static int read_sections(struct elf *elf)
 			}
 		}
 
-		if (sec->sh.sh_flags & SHF_EXECINSTR)
-			elf->text_size += sec->sh.sh_size;
-
 		list_add_tail(&sec->list, &elf->sections);
 		elf_hash_add(section, &sec->hash, sec->idx);
 		elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
+
+		if (is_reloc_sec(sec))
+			elf->num_relocs += sec->sh.sh_size / sec->sh.sh_entsize;
 	}
 
 	if (opts.stats) {
@@ -888,19 +888,18 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 
 static int read_relocs(struct elf *elf)
 {
-	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
+	unsigned long nr_reloc, max_reloc = 0;
 	struct section *rsec;
 	struct reloc *reloc;
 	unsigned int symndx;
 	struct symbol *sym;
 	int i;
 
-	if (!elf_alloc_hash(reloc, elf->text_size / 16))
+	if (!elf_alloc_hash(reloc, elf->num_relocs))
 		return -1;
 
 	list_for_each_entry(rsec, &elf->sections, list) {
-		if ((rsec->sh.sh_type != SHT_RELA) &&
-		    (rsec->sh.sh_type != SHT_REL))
+		if (!is_reloc_sec(rsec))
 			continue;
 
 		rsec->base = find_section_by_index(elf, rsec->sh.sh_info);
@@ -942,12 +941,11 @@ static int read_relocs(struct elf *elf)
 			nr_reloc++;
 		}
 		max_reloc = max(max_reloc, nr_reloc);
-		tot_reloc += nr_reloc;
 	}
 
 	if (opts.stats) {
 		printf("max_reloc: %lu\n", max_reloc);
-		printf("tot_reloc: %lu\n", tot_reloc);
+		printf("num_relocs: %lu\n", elf->num_relocs);
 		printf("reloc_bits: %d\n", elf->reloc_bits);
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 6f82f2515d6b..b81d78b35126 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -90,8 +90,9 @@ struct elf {
 	int fd;
 	bool changed;
 	char *name;
-	unsigned int text_size, num_files;
+	unsigned int num_files;
 	struct list_head sections;
+	unsigned long num_relocs;
 
 	int symbol_bits;
 	int symbol_name_bits;
@@ -158,6 +159,11 @@ static inline size_t elf_rela_size(struct elf *elf)
 	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
+static inline bool is_reloc_sec(struct section *sec)
+{
+	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 06/22] objtool: Add mark_sec_changed()
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (4 preceding siblings ...)
  2023-05-30 17:20 ` [PATCH 05/22] objtool: Fix reloc_hash size Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:20 ` [PATCH 07/22] objtool: Add elf_create_section_pair() Josh Poimboeuf
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Ensure elf->changed always gets set when sec->changed gets set.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 31 +++++++++++++++--------------
 tools/objtool/include/objtool/elf.h | 14 ++++++++++++-
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index f72ec6d8fb14..67967c231972 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -562,7 +562,8 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
-	sec->rsec->changed = true;
+
+	mark_sec_changed(elf, sec->rsec, true);
 
 	return 0;
 }
@@ -577,7 +578,7 @@ static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym)
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry)
-		reloc->sec->changed = true;
+		mark_sec_changed(elf, reloc->sec, true);
 }
 
 /*
@@ -654,7 +655,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
 			symtab_data->d_align = 1;
 			symtab_data->d_type = ELF_T_SYM;
 
-			symtab->changed = true;
+			mark_sec_changed(elf, symtab, true);
 			symtab->truncate = true;
 
 			if (t) {
@@ -669,7 +670,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
 				shndx_data->d_align = sizeof(Elf32_Word);
 				shndx_data->d_type = ELF_T_WORD;
 
-				symtab_shndx->changed = true;
+				mark_sec_changed(elf, symtab_shndx, true);
 				symtab_shndx->truncate = true;
 			}
 
@@ -773,11 +774,11 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 	}
 
 	symtab->sh.sh_size += symtab->sh.sh_entsize;
-	symtab->changed = true;
+	mark_sec_changed(elf, symtab, true);
 
 	if (symtab_shndx) {
 		symtab_shndx->sh.sh_size += sizeof(Elf32_Word);
-		symtab_shndx->changed = true;
+		mark_sec_changed(elf, symtab_shndx, true);
 	}
 
 	return sym;
@@ -1040,7 +1041,8 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 
 	len = strtab->sh.sh_size;
 	strtab->sh.sh_size += data->d_size;
-	strtab->changed = true;
+
+	mark_sec_changed(elf, strtab, true);
 
 	return len;
 }
@@ -1075,7 +1077,6 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	}
 
 	sec->idx = elf_ndxscn(s);
-	sec->changed = true;
 
 	sec->data = elf_newdata(s);
 	if (!sec->data) {
@@ -1122,7 +1123,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	elf_hash_add(section, &sec->hash, sec->idx);
 	elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
 
-	elf->changed = true;
+	mark_sec_changed(elf, sec, true);
 
 	return sec;
 }
@@ -1208,9 +1209,8 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 	}
 
 	memcpy(data->d_buf + offset, insn, len);
-	elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
 
-	elf->changed = true;
+	mark_sec_changed(elf, sec, true);
 
 	return 0;
 }
@@ -1235,7 +1235,7 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 		return -1;
 	}
 
-	elf->changed = true;
+	mark_sec_changed(elf, rsec, true);
 
 	return 0;
 }
@@ -1307,12 +1307,14 @@ int elf_write(struct elf *elf)
 		if (sec->truncate)
 			elf_truncate_section(elf, sec);
 
-		if (sec->changed) {
+		if (sec_changed(sec)) {
 			s = elf_getscn(elf->elf, sec->idx);
 			if (!s) {
 				WARN_ELF("elf_getscn");
 				return -1;
 			}
+
+			/* Note this also flags the section dirty */
 			if (!gelf_update_shdr(s, &sec->sh)) {
 				WARN_ELF("gelf_update_shdr");
 				return -1;
@@ -1324,8 +1326,7 @@ int elf_write(struct elf *elf)
 				return -1;
 			}
 
-			sec->changed = false;
-			elf->changed = true;
+			mark_sec_changed(elf, sec, false);
 		}
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index b81d78b35126..56b66ff91943 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	Elf_Data *data;
 	char *name;
 	int idx;
-	bool changed, text, rodata, noinstr, init, truncate;
+	bool _changed, text, rodata, noinstr, init, truncate;
 	struct reloc *reloc_data;
 };
 
@@ -164,6 +164,18 @@ static inline bool is_reloc_sec(struct section *sec)
 	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
 }
 
+static inline bool sec_changed(struct section *sec)
+{
+	return sec->_changed;
+}
+
+static inline void mark_sec_changed(struct elf *elf, struct section *sec,
+				    bool changed)
+{
+	sec->_changed = changed;
+	elf->changed |= changed;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 07/22] objtool: Add elf_create_section_pair()
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (5 preceding siblings ...)
  2023-05-30 17:20 ` [PATCH 06/22] objtool: Add mark_sec_changed() Josh Poimboeuf
@ 2023-05-30 17:20 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 08/22] objtool: Keep GElf_Rel[a] structs synced Josh Poimboeuf
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:20 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

When creating an annotation section, allocate the reloc section data at
the beginning.  This simplifies the data model a bit and also saves
memory due to the removal of malloc() in elf_rebuild_reloc_section().

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 53.49G
- After:  peak heap memory consumption: 49.02G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/powerpc/include/arch/elf.h |  11 +-
 tools/objtool/arch/x86/include/arch/elf.h     |  11 +-
 tools/objtool/check.c                         | 129 ++++++---------
 tools/objtool/elf.c                           | 151 +++++++++++-------
 tools/objtool/include/objtool/elf.h           |  33 +++-
 tools/objtool/orc_gen.c                       |   6 +-
 6 files changed, 184 insertions(+), 157 deletions(-)

diff --git a/tools/objtool/arch/powerpc/include/arch/elf.h b/tools/objtool/arch/powerpc/include/arch/elf.h
index 73f9ae172fe5..66814fa28024 100644
--- a/tools/objtool/arch/powerpc/include/arch/elf.h
+++ b/tools/objtool/arch/powerpc/include/arch/elf.h
@@ -1,10 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
-
 #ifndef _OBJTOOL_ARCH_ELF
 #define _OBJTOOL_ARCH_ELF
 
-#define R_NONE R_PPC_NONE
-#define R_ABS64 R_PPC64_ADDR64
-#define R_ABS32 R_PPC_ADDR32
+#define R_NONE		R_PPC_NONE
+#define R_ABS64		R_PPC64_ADDR64
+#define R_ABS32		R_PPC_ADDR32
+#define R_DATA32	R_PPC_REL32
+#define R_DATA64	R_PPC64_REL64
+#define R_TEXT32	R_PPC_REL32
+#define R_TEXT64	R_PPC64_REL32
 
 #endif /* _OBJTOOL_ARCH_ELF */
diff --git a/tools/objtool/arch/x86/include/arch/elf.h b/tools/objtool/arch/x86/include/arch/elf.h
index ac14987cf687..7131f7f51a4e 100644
--- a/tools/objtool/arch/x86/include/arch/elf.h
+++ b/tools/objtool/arch/x86/include/arch/elf.h
@@ -1,8 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 #ifndef _OBJTOOL_ARCH_ELF
 #define _OBJTOOL_ARCH_ELF
 
-#define R_NONE R_X86_64_NONE
-#define R_ABS64 R_X86_64_64
-#define R_ABS32 R_X86_64_32
+#define R_NONE		R_X86_64_NONE
+#define R_ABS32		R_X86_64_32
+#define R_ABS64		R_X86_64_64
+#define R_DATA32	R_X86_64_PC32
+#define R_DATA64	R_X86_64_PC32
+#define R_TEXT32	R_X86_64_PC32
+#define R_TEXT64	R_X86_64_PC32
 
 #endif /* _OBJTOOL_ARCH_ELF */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index b6d0cb24085b..88f54bb1b01c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -8,7 +8,6 @@
 #include <inttypes.h>
 #include <sys/mman.h>
 
-#include <arch/elf.h>
 #include <objtool/builtin.h>
 #include <objtool/cfi.h>
 #include <objtool/arch.h>
@@ -655,8 +654,8 @@ static int add_dead_ends(struct objtool_file *file)
 
 static int create_static_call_sections(struct objtool_file *file)
 {
-	struct section *sec;
 	struct static_call_site *site;
+	struct section *sec;
 	struct instruction *insn;
 	struct symbol *key_sym;
 	char *key_name, *tmp;
@@ -676,25 +675,21 @@ static int create_static_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->static_call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".static_call_sites",
-				 sizeof(struct static_call_site), idx);
+	sec = elf_create_section_pair(file->elf, ".static_call_sites",
+				      sizeof(*site), idx, idx * 2);
 	if (!sec)
 		return -1;
 
-	/* Allow modules to set the low bits of static_call_site::key */
+	/* Allow modules to modify the low bits of static_call_site::key */
 	sec->sh.sh_flags |= SHF_WRITE;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->static_call_list, call_node) {
 
-		site = (struct static_call_site *)sec->data->d_buf + idx;
-		memset(site, 0, sizeof(struct static_call_site));
-
 		/* populate reloc for 'addr' */
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(struct static_call_site),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(*site), idx * 2,
+					     insn->sec, insn->offset))
 			return -1;
 
 		/* find key symbol */
@@ -734,10 +729,10 @@ static int create_static_call_sections(struct objtool_file *file)
 		free(key_name);
 
 		/* populate reloc for 'key' */
-		if (elf_add_reloc(file->elf, sec,
-				  idx * sizeof(struct static_call_site) + 4,
-				  R_X86_64_PC32, key_sym,
-				  is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
+		if (!elf_init_reloc_data_sym(file->elf, sec,
+					     idx * sizeof(*site) + 4,
+					     (idx * 2) + 1, key_sym,
+					     is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
 			return -1;
 
 		idx++;
@@ -765,26 +760,18 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".retpoline_sites",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .retpoline_sites");
+	sec = elf_create_section_pair(file->elf, ".retpoline_sites",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
 
-		int *site = (int *)sec->data->d_buf + idx;
-		*site = 0;
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .retpoline_sites");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -811,26 +798,18 @@ static int create_return_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".return_sites",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .return_sites");
+	sec = elf_create_section_pair(file->elf, ".return_sites",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->return_thunk_list, call_node) {
 
-		int *site = (int *)sec->data->d_buf + idx;
-		*site = 0;
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .return_sites");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -863,12 +842,10 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".ibt_endbr_seal",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .ibt_endbr_seal");
+	sec = elf_create_section_pair(file->elf, ".ibt_endbr_seal",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->endbr_list, call_node) {
@@ -883,13 +860,10 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 		     !strcmp(sym->name, "cleanup_module")))
 			WARN("%s(): not an indirect call target", sym->name);
 
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .ibt_endbr_seal");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -901,7 +875,6 @@ static int create_cfi_sections(struct objtool_file *file)
 {
 	struct section *sec;
 	struct symbol *sym;
-	unsigned int *loc;
 	int idx;
 
 	sec = find_section_by_name(file->elf, ".cfi_sites");
@@ -922,7 +895,8 @@ static int create_cfi_sections(struct objtool_file *file)
 		idx++;
 	}
 
-	sec = elf_create_section(file->elf, ".cfi_sites", sizeof(unsigned int), idx);
+	sec = elf_create_section_pair(file->elf, ".cfi_sites",
+				      sizeof(unsigned int), idx, idx);
 	if (!sec)
 		return -1;
 
@@ -934,13 +908,9 @@ static int create_cfi_sections(struct objtool_file *file)
 		if (strncmp(sym->name, "__cfi_", 6))
 			continue;
 
-		loc = (unsigned int *)sec->data->d_buf + idx;
-		memset(loc, 0, sizeof(unsigned int));
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(unsigned int),
-					  R_X86_64_PC32,
-					  sym->sec, sym->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(unsigned int), idx,
+					     sym->sec, sym->offset))
 			return -1;
 
 		idx++;
@@ -970,7 +940,8 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", addr_size, idx);
+	sec = elf_create_section_pair(file->elf, "__mcount_loc", addr_size,
+				      idx, idx);
 	if (!sec)
 		return -1;
 
@@ -978,17 +949,17 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 
 	idx = 0;
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
-		void *loc;
 
-		loc = sec->data->d_buf + idx;
-		memset(loc, 0, addr_size);
+		struct reloc *reloc;
 
-		if (elf_add_reloc_to_insn(file->elf, sec, idx,
-					  addr_size == sizeof(u64) ? R_ABS64 : R_ABS32,
-					  insn->sec, insn->offset))
+		reloc = elf_init_reloc_text_sym(file->elf, sec, idx * addr_size, idx,
+					       insn->sec, insn->offset);
+		if (!reloc)
 			return -1;
 
-		idx += addr_size;
+		reloc->type = addr_size == 8 ? R_ABS64 : R_ABS32;
+
+		idx++;
 	}
 
 	return 0;
@@ -998,7 +969,6 @@ static int create_direct_call_sections(struct objtool_file *file)
 {
 	struct instruction *insn;
 	struct section *sec;
-	unsigned int *loc;
 	int idx;
 
 	sec = find_section_by_name(file->elf, ".call_sites");
@@ -1015,20 +985,17 @@ static int create_direct_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".call_sites", sizeof(unsigned int), idx);
+	sec = elf_create_section_pair(file->elf, ".call_sites",
+				      sizeof(unsigned int), idx, idx);
 	if (!sec)
 		return -1;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->call_list, call_node) {
 
-		loc = (unsigned int *)sec->data->d_buf + idx;
-		memset(loc, 0, sizeof(unsigned int));
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(unsigned int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(unsigned int), idx,
+					     insn->sec, insn->offset))
 			return -1;
 
 		idx++;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 67967c231972..5cbc9d578a45 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -533,41 +533,6 @@ static int read_symbols(struct elf *elf)
 	return -1;
 }
 
-static struct section *elf_create_rela_section(struct elf *elf,
-					       struct section *sec);
-
-int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
-		  unsigned int type, struct symbol *sym, s64 addend)
-{
-	struct reloc *reloc;
-
-	if (!sec->rsec && !elf_create_rela_section(elf, sec))
-		return -1;
-
-	reloc = malloc(sizeof(*reloc));
-	if (!reloc) {
-		perror("malloc");
-		return -1;
-	}
-	memset(reloc, 0, sizeof(*reloc));
-
-	reloc->sec = sec->rsec;
-	reloc->offset = offset;
-	reloc->type = type;
-	reloc->sym = sym;
-	reloc->addend = addend;
-
-	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &sec->rsec->reloc_list);
-	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
-
-	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
-
-	mark_sec_changed(elf, sec->rsec, true);
-
-	return 0;
-}
-
 /*
  * Ensure that any reloc section containing references to @sym is marked
  * changed such that it will get re-generated in elf_rebuild_reloc_sections()
@@ -841,13 +806,57 @@ elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size)
 	return sym;
 }
 
-int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
-			  unsigned long offset, unsigned int type,
-			  struct section *insn_sec, unsigned long insn_off)
+static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
+				    unsigned int reloc_idx,
+				    unsigned long offset, struct symbol *sym,
+				    s64 addend, unsigned int type)
+{
+	struct reloc *reloc;
+
+	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
+		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
+		     __func__, reloc_idx, rsec->name, rsec->sh.sh_size);
+		return NULL;
+	}
+
+	reloc = malloc(sizeof(*reloc));
+	if (!reloc) {
+		perror("malloc");
+		return NULL;
+	}
+	memset(reloc, 0, sizeof(*reloc));
+
+	reloc->idx = reloc_idx;
+	reloc->sec = rsec;
+	reloc->offset = offset;
+	reloc->type = type;
+	reloc->sym = sym;
+	reloc->addend = addend;
+
+	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
+	list_add_tail(&reloc->list, &rsec->reloc_list);
+	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+
+	mark_sec_changed(elf, rsec, true);
+
+	return reloc;
+}
+
+struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct section *insn_sec,
+				      unsigned long insn_off)
 {
 	struct symbol *sym = insn_sec->sym;
 	int addend = insn_off;
 
+	if (!(insn_sec->sh.sh_flags & SHF_EXECINSTR)) {
+		WARN("bad call to %s() for data symbol %s",
+		     __func__, sym->name);
+		return NULL;
+	}
+
 	if (!sym) {
 		/*
 		 * Due to how weak functions work, we must use section based
@@ -857,12 +866,29 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 		 */
 		sym = elf_create_section_symbol(elf, insn_sec);
 		if (!sym)
-			return -1;
+			return NULL;
 
 		insn_sec->sym = sym;
 	}
 
-	return elf_add_reloc(elf, sec, offset, type, sym, addend);
+	return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend,
+			      elf_text_rela_type(elf));
+}
+
+struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct symbol *sym,
+				      s64 addend)
+{
+	if (sym->sec && (sec->sh.sh_flags & SHF_EXECINSTR)) {
+		WARN("bad call to %s() for text symbol %s",
+		     __func__, sym->name);
+		return NULL;
+	}
+
+	return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend,
+			      elf_data_rela_type(elf));
 }
 
 static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
@@ -1048,7 +1074,7 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 }
 
 struct section *elf_create_section(struct elf *elf, const char *name,
-				   size_t entsize, int nr)
+				   size_t entsize, unsigned int nr)
 {
 	struct section *sec, *shstrtab;
 	size_t size = entsize * nr;
@@ -1129,7 +1155,8 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 }
 
 static struct section *elf_create_rela_section(struct elf *elf,
-					       struct section *sec)
+					       struct section *sec,
+					       unsigned int reloc_nr)
 {
 	struct section *rsec;
 	char *rsec_name;
@@ -1142,46 +1169,50 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	strcpy(rsec_name, ".rela");
 	strcat(rsec_name, sec->name);
 
-	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), 0);
+	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), reloc_nr);
 	free(rsec_name);
 	if (!rsec)
 		return NULL;
 
-	sec->rsec = rsec;
-	rsec->base = sec;
-
+	rsec->data->d_type = ELF_T_RELA;
 	rsec->sh.sh_type = SHT_RELA;
 	rsec->sh.sh_addralign = elf_addr_size(elf);
 	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
+	sec->rsec = rsec;
+	rsec->base = sec;
+
 	return rsec;
 }
 
+struct section *elf_create_section_pair(struct elf *elf, const char *name,
+					size_t entsize, unsigned int nr,
+					unsigned int reloc_nr)
+{
+	struct section *sec;
+
+	sec = elf_create_section(elf, name, entsize, nr);
+	if (!sec)
+		return NULL;
+
+	if (!elf_create_rela_section(elf, sec, reloc_nr))
+		return NULL;
+
+	return sec;
+}
+
 static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
-	bool rela = rsec->sh.sh_type == SHT_RELA;
 	struct reloc *reloc;
 	int idx = 0, ret;
-	void *buf;
-
-	/* Allocate a buffer for relocations */
-	buf = malloc(rsec->sh.sh_size);
-	if (!buf) {
-		perror("malloc");
-		return -1;
-	}
-
-	rsec->data->d_buf = buf;
-	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = rela ? ELF_T_RELA : ELF_T_REL;
 
 	idx = 0;
 	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (rela) {
+		if (rsec->sh.sh_type == SHT_RELA) {
 			reloc->rela.r_addend = reloc->addend;
 			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
 		} else {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 56b66ff91943..74f63934afd3 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -111,15 +111,26 @@ struct elf {
 };
 
 struct elf *elf_open_read(const char *name, int flags);
-struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
+
+struct section *elf_create_section(struct elf *elf, const char *name,
+				   size_t entsize, unsigned int nr);
+struct section *elf_create_section_pair(struct elf *elf, const char *name,
+					size_t entsize, unsigned int nr,
+					unsigned int reloc_nr);
 
 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
 
-int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
-		  unsigned int type, struct symbol *sym, s64 addend);
-int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
-			  unsigned long offset, unsigned int type,
-			  struct section *insn_sec, unsigned long insn_off);
+struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct section *insn_sec,
+				      unsigned long insn_off);
+
+struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct symbol *sym,
+				      s64 addend);
 
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
@@ -159,6 +170,16 @@ static inline size_t elf_rela_size(struct elf *elf)
 	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
+static inline unsigned int elf_data_rela_type(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? R_DATA32 : R_DATA64;
+}
+
+static inline unsigned int elf_text_rela_type(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64;
+}
+
 static inline bool is_reloc_sec(struct section *sec)
 {
 	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index d5f750be7d7d..bae343908867 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -118,8 +118,8 @@ static int write_orc_entry(struct elf *elf, struct section *orc_sec,
 	orc->bp_offset = bswap_if_needed(elf, orc->bp_offset);
 
 	/* populate reloc for ip */
-	if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32,
-				  insn_sec, insn_off))
+	if (!elf_init_reloc_text_sym(elf, ip_sec, idx * sizeof(int), idx,
+				     insn_sec, insn_off))
 		return -1;
 
 	return 0;
@@ -242,7 +242,7 @@ int orc_create(struct objtool_file *file)
 	if (!orc_sec)
 		return -1;
 
-	sec = elf_create_section(file->elf, ".orc_unwind_ip", sizeof(int), nr);
+	sec = elf_create_section_pair(file->elf, ".orc_unwind_ip", sizeof(int), nr, nr);
 	if (!sec)
 		return -1;
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 08/22] objtool: Keep GElf_Rel[a] structs synced
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (6 preceding siblings ...)
  2023-05-30 17:20 ` [PATCH 07/22] objtool: Add elf_create_section_pair() Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 09/22] objtool: Don't free memory in elf_close() Josh Poimboeuf
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Keep the GElf_Rela structs synced with their 'struct reloc' counterparts
instead of having to go back and "rebuild" them later.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 55 ++++++++++++---------------------------------
 1 file changed, 14 insertions(+), 41 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 5cbc9d578a45..8d491b2d123e 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -534,16 +534,18 @@ static int read_symbols(struct elf *elf)
 }
 
 /*
- * Ensure that any reloc section containing references to @sym is marked
- * changed such that it will get re-generated in elf_rebuild_reloc_sections()
- * with the new symbol index.
+ * @sym's idx has changed.  Update the relocs which reference it.
  */
-static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym)
+static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry)
-		mark_sec_changed(elf, reloc->sec, true);
+	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+		if (elf_write_reloc(elf, reloc))
+			return -1;
+	}
+
+	return 0;
 }
 
 /*
@@ -716,13 +718,14 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 		hlist_del(&old->hash);
 		elf_hash_add(symbol, &old->hash, old->idx);
 
-		elf_dirty_reloc_sym(elf, old);
-
 		if (elf_update_symbol(elf, symtab, symtab_shndx, old)) {
 			WARN("elf_update_symbol move");
 			return NULL;
 		}
 
+		if (elf_update_sym_relocs(elf, old))
+			return NULL;
+
 		new_idx = first_non_local;
 	}
 
@@ -833,12 +836,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	reloc->sym = sym;
 	reloc->addend = addend;
 
+	if (elf_write_reloc(elf, reloc))
+		return NULL;
+
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 	list_add_tail(&reloc->list, &rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
-	mark_sec_changed(elf, rsec, true);
-
 	return reloc;
 }
 
@@ -1203,31 +1207,6 @@ struct section *elf_create_section_pair(struct elf *elf, const char *name,
 	return sec;
 }
 
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
-{
-	struct reloc *reloc;
-	int idx = 0, ret;
-
-	idx = 0;
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
-		reloc->rel.r_offset = reloc->offset;
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (rsec->sh.sh_type == SHT_RELA) {
-			reloc->rela.r_addend = reloc->addend;
-			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
-		} else {
-			ret = gelf_update_rel(rsec->data, idx, &reloc->rel);
-		}
-		if (!ret) {
-			WARN_ELF("gelf_update_rel");
-			return -1;
-		}
-		idx++;
-	}
-
-	return 0;
-}
-
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn)
@@ -1351,12 +1330,6 @@ int elf_write(struct elf *elf)
 				return -1;
 			}
 
-			if (sec->base &&
-			    elf_rebuild_reloc_section(elf, sec)) {
-				WARN("elf_rebuild_reloc_section");
-				return -1;
-			}
-
 			mark_sec_changed(elf, sec, false);
 		}
 	}
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 09/22] objtool: Don't free memory in elf_close()
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (7 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 08/22] objtool: Keep GElf_Rel[a] structs synced Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 10/22] objtool: Add for_each_reloc() Josh Poimboeuf
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

It's not necessary, objtool's about to exit anyway.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8d491b2d123e..8d53f18a9502 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -1350,30 +1350,14 @@ int elf_write(struct elf *elf)
 
 void elf_close(struct elf *elf)
 {
-	struct section *sec, *tmpsec;
-	struct symbol *sym, *tmpsym;
-	struct reloc *reloc, *tmpreloc;
-
 	if (elf->elf)
 		elf_end(elf->elf);
 
 	if (elf->fd > 0)
 		close(elf->fd);
 
-	list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) {
-		list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
-			list_del(&sym->list);
-			hash_del(&sym->hash);
-		}
-		list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) {
-			list_del(&reloc->list);
-			hash_del(&reloc->hash);
-		}
-		list_del(&sec->list);
-		free(sec->reloc_data);
-	}
-
-	free(elf->symbol_data);
-	free(elf->section_data);
-	free(elf);
+	/*
+	 * NOTE: All remaining allocations are leaked on purpose.  Objtool is
+	 * about to exit anyway.
+	 */
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 10/22] objtool: Add for_each_reloc()
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (8 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 09/22] objtool: Don't free memory in elf_close() Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 11/22] objtool: Allocate relocs in advance for new rela sections Josh Poimboeuf
                   ` (11 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 24 ++++++++++++------------
 tools/objtool/include/objtool/elf.h |  6 ++++++
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 88f54bb1b01c..1355e6fec7d6 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -590,7 +590,7 @@ static int add_dead_ends(struct objtool_file *file)
 	if (!rsec)
 		goto reachable;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -625,7 +625,7 @@ static int add_dead_ends(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -1018,7 +1018,7 @@ static void add_ignores(struct objtool_file *file)
 	if (!rsec)
 		return;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		switch (reloc->sym->type) {
 		case STT_FUNC:
 			func = reloc->sym;
@@ -1259,7 +1259,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -1990,7 +1990,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 	 * Each @reloc is a switch table relocation which points to the target
 	 * instruction.
 	 */
-	list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {
+	for_each_reloc_from(table->sec, reloc) {
 
 		/* Check for the end of the table: */
 		if (reloc != table && reloc->jump_table_start)
@@ -2264,7 +2264,7 @@ static int read_noendbr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
@@ -2287,7 +2287,7 @@ static int read_retpoline_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2323,7 +2323,7 @@ static int read_instr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2342,7 +2342,7 @@ static int read_instr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2370,7 +2370,7 @@ static int read_validate_unret_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2398,7 +2398,7 @@ static int read_intra_function_calls(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		unsigned long dest_off;
 
 		if (reloc->sym->type != STT_SECTION) {
@@ -4395,7 +4395,7 @@ static int validate_ibt(struct objtool_file *file)
 		    strstr(sec->name, "__patchable_function_entries"))
 			continue;
 
-		list_for_each_entry(reloc, &sec->rsec->reloc_list, list)
+		for_each_reloc(sec->rsec, reloc)
 			warnings += validate_ibt_data_reloc(file, reloc);
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 74f63934afd3..a938cb1d4172 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -209,6 +209,12 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 		for_each_sec(file, __sec)				\
 			sec_for_each_sym(__sec, sym)
 
+#define for_each_reloc(rsec, reloc)					\
+	list_for_each_entry(reloc, &rsec->reloc_list, list)
+
+#define for_each_reloc_from(rsec, reloc)				\
+	list_for_each_entry_from(reloc, &rsec->reloc_list, list)
+
 #define OFFSET_STRIDE_BITS	4
 #define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
 #define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 11/22] objtool: Allocate relocs in advance for new rela sections
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (9 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 10/22] objtool: Add for_each_reloc() Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 12/22] objtool: Get rid of reloc->list Josh Poimboeuf
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Similar to read_relocs(), allocate the reloc structs all together in an
array rather than allocating them one at a time.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8d53f18a9502..5f69d4590117 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -814,7 +814,7 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 				    unsigned long offset, struct symbol *sym,
 				    s64 addend, unsigned int type)
 {
-	struct reloc *reloc;
+	struct reloc *reloc, empty = { 0 };
 
 	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
 		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
@@ -822,12 +822,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 	}
 
-	reloc = malloc(sizeof(*reloc));
-	if (!reloc) {
-		perror("malloc");
+	reloc = &rsec->reloc_data[reloc_idx];
+
+	if (memcmp(reloc, &empty, sizeof(empty))) {
+		WARN("%s: %s: reloc %d already initialized!",
+		     __func__, rsec->name, reloc_idx);
 		return NULL;
 	}
-	memset(reloc, 0, sizeof(*reloc));
 
 	reloc->idx = reloc_idx;
 	reloc->sec = rsec;
@@ -1185,6 +1186,13 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
+	rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
+				  sizeof(struct reloc));
+	if (!rsec->reloc_data) {
+		perror("calloc");
+		return NULL;
+	}
+
 	sec->rsec = rsec;
 	rsec->base = sec;
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 12/22] objtool: Get rid of reloc->list
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (10 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 11/22] objtool: Allocate relocs in advance for new rela sections Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 13/22] objtool: Get rid of reloc->idx Josh Poimboeuf
                   ` (9 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Now that all relocs are allocated in an array, the linked list is no
longer needed.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 49.02G
- After:  peak heap memory consumption: 45.56G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 32 ++++++++++++-----------------
 tools/objtool/include/objtool/elf.h | 18 +++++++++++-----
 2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 5f69d4590117..19ac53ad76ee 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -293,7 +293,6 @@ static int read_sections(struct elf *elf)
 		sec = &elf->section_data[i];
 
 		INIT_LIST_HEAD(&sec->symbol_list);
-		INIT_LIST_HEAD(&sec->reloc_list);
 
 		s = elf_getscn(elf->elf, i);
 		if (!s) {
@@ -333,7 +332,7 @@ static int read_sections(struct elf *elf)
 		elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
 
 		if (is_reloc_sec(sec))
-			elf->num_relocs += sec->sh.sh_size / sec->sh.sh_entsize;
+			elf->num_relocs += sec_num_entries(sec);
 	}
 
 	if (opts.stats) {
@@ -407,7 +406,7 @@ static int read_symbols(struct elf *elf)
 		if (symtab_shndx)
 			shndx_data = symtab_shndx->data;
 
-		symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize;
+		symbols_nr = sec_num_entries(symtab);
 	} else {
 		/*
 		 * A missing symbol table is actually possible if it's an empty
@@ -701,7 +700,7 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 		return NULL;
 	}
 
-	new_idx = symtab->sh.sh_size / symtab->sh.sh_entsize;
+	new_idx = sec_num_entries(symtab);
 
 	if (GELF_ST_BIND(sym->sym.st_info) != STB_LOCAL)
 		goto non_local;
@@ -816,13 +815,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 {
 	struct reloc *reloc, empty = { 0 };
 
-	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
-		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
-		     __func__, reloc_idx, rsec->name, rsec->sh.sh_size);
+	if (reloc_idx >= sec_num_entries(rsec)) {
+		WARN("%s: bad reloc_idx %u for %s with %d relocs",
+		     __func__, reloc_idx, rsec->name, sec_num_entries(rsec));
 		return NULL;
 	}
 
-	reloc = &rsec->reloc_data[reloc_idx];
+	reloc = &rsec->relocs[reloc_idx];
 
 	if (memcmp(reloc, &empty, sizeof(empty))) {
 		WARN("%s: %s: reloc %d already initialized!",
@@ -841,7 +840,6 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 	return reloc;
@@ -944,14 +942,13 @@ static int read_relocs(struct elf *elf)
 		rsec->base->rsec = rsec;
 
 		nr_reloc = 0;
-		rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
-					  sizeof(*reloc));
-		if (!rsec->reloc_data) {
+		rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc));
+		if (!rsec->relocs) {
 			perror("calloc");
 			return -1;
 		}
-		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
-			reloc = &rsec->reloc_data[i];
+		for (i = 0; i < sec_num_entries(rsec); i++) {
+			reloc = &rsec->relocs[i];
 
 			if (read_reloc(rsec, i, reloc))
 				return -1;
@@ -967,7 +964,6 @@ static int read_relocs(struct elf *elf)
 			}
 
 			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-			list_add_tail(&reloc->list, &rsec->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 			nr_reloc++;
@@ -1093,7 +1089,6 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	memset(sec, 0, sizeof(*sec));
 
 	INIT_LIST_HEAD(&sec->symbol_list);
-	INIT_LIST_HEAD(&sec->reloc_list);
 
 	s = elf_newscn(elf->elf);
 	if (!s) {
@@ -1186,9 +1181,8 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
-				  sizeof(struct reloc));
-	if (!rsec->reloc_data) {
+	rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
+	if (!rsec->relocs) {
 		perror("calloc");
 		return NULL;
 	}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a938cb1d4172..a09da208ddb8 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -33,14 +33,13 @@ struct section {
 	GElf_Shdr sh;
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
-	struct list_head reloc_list;
 	struct section *base, *rsec;
 	struct symbol *sym;
 	Elf_Data *data;
 	char *name;
 	int idx;
 	bool _changed, text, rodata, noinstr, init, truncate;
-	struct reloc *reloc_data;
+	struct reloc *relocs;
 };
 
 struct symbol {
@@ -68,7 +67,6 @@ struct symbol {
 };
 
 struct reloc {
-	struct list_head list;
 	struct hlist_node hash;
 	union {
 		GElf_Rela rela;
@@ -197,6 +195,11 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 	elf->changed |= changed;
 }
 
+static inline unsigned int sec_num_entries(struct section *sec)
+{
+	return sec->sh.sh_size / sec->sh.sh_entsize;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -210,10 +213,15 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 			sec_for_each_sym(__sec, sym)
 
 #define for_each_reloc(rsec, reloc)					\
-	list_for_each_entry(reloc, &rsec->reloc_list, list)
+	for (int __i = 0, __fake = 1; __fake; __fake = 0)		\
+		for (reloc = rsec->relocs;				\
+		     __i < sec_num_entries(rsec);			\
+		     __i++, reloc++)
 
 #define for_each_reloc_from(rsec, reloc)				\
-	list_for_each_entry_from(reloc, &rsec->reloc_list, list)
+	for (int __i = reloc->idx;					\
+	     __i < sec_num_entries(rsec);				\
+	     __i++, reloc++)
 
 #define OFFSET_STRIDE_BITS	4
 #define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 13/22] objtool: Get rid of reloc->idx
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (11 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 12/22] objtool: Get rid of reloc->list Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 14/22] objtool: Get rid of reloc->offset Josh Poimboeuf
                   ` (8 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Use the array offset to calculate the reloc index.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 45.56G
- After:  peak heap memory consumption: 43.83G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 |  6 ++----
 tools/objtool/include/objtool/elf.h | 10 +++++++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 19ac53ad76ee..70c801254566 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -829,7 +829,6 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 	}
 
-	reloc->idx = reloc_idx;
 	reloc->sec = rsec;
 	reloc->offset = offset;
 	reloc->type = type;
@@ -954,7 +953,6 @@ static int read_relocs(struct elf *elf)
 				return -1;
 
 			reloc->sec = rsec;
-			reloc->idx = i;
 			symndx = GELF_R_SYM(reloc->rel.r_info);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
@@ -1237,9 +1235,9 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 
 	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
-		ret = gelf_update_rela(rsec->data, reloc->idx, &reloc->rela);
+		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
 	} else {
-		ret = gelf_update_rel(rsec->data, reloc->idx, &reloc->rel);
+		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
 	}
 
 	if (!ret) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a09da208ddb8..2a14da633d56 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -76,9 +76,8 @@ struct reloc {
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
 	unsigned long offset;
-	unsigned int type;
 	s64 addend;
-	int idx;
+	unsigned int type;
 	bool jump_table_start;
 };
 
@@ -200,6 +199,11 @@ static inline unsigned int sec_num_entries(struct section *sec)
 	return sec->sh.sh_size / sec->sh.sh_entsize;
 }
 
+static inline unsigned int reloc_idx(struct reloc *reloc)
+{
+	return reloc - reloc->sec->relocs;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -219,7 +223,7 @@ static inline unsigned int sec_num_entries(struct section *sec)
 		     __i++, reloc++)
 
 #define for_each_reloc_from(rsec, reloc)				\
-	for (int __i = reloc->idx;					\
+	for (int __i = reloc_idx(reloc);				\
 	     __i < sec_num_entries(rsec);				\
 	     __i++, reloc++)
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 14/22] objtool: Get rid of reloc->offset
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (12 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 13/22] objtool: Get rid of reloc->idx Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 15/22] objtool: Get rid of reloc->type Josh Poimboeuf
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Get the offset from the embedded GElf_Rel[a] struct.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 43.83G
- After:  peak heap memory consumption: 42.10G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 14 +++++++-------
 tools/objtool/elf.c                 | 10 +++++-----
 tools/objtool/include/objtool/elf.h |  8 ++++++--
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 1355e6fec7d6..440c326121d4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -510,11 +510,11 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 		if (func->type == STT_SECTION)
 			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
 
-		idx = (reloc->offset - sym->offset) / sizeof(unsigned long);
+		idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 
 		objtool_pv_add(file, idx, func);
 
-		off = reloc->offset + 1;
+		off = reloc_offset(reloc) + 1;
 		if (off > end)
 			break;
 	}
@@ -1997,7 +1997,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 			break;
 
 		/* Make sure the table entries are consecutive: */
-		if (prev_offset && reloc->offset != prev_offset + 8)
+		if (prev_offset && reloc_offset(reloc) != prev_offset + 8)
 			break;
 
 		/* Detect function pointers from contiguous objects: */
@@ -2022,7 +2022,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 		alt->insn = dest_insn;
 		alt->next = insn->alts;
 		insn->alts = alt;
-		prev_offset = reloc->offset;
+		prev_offset = reloc_offset(reloc);
 	}
 
 	if (!prev_offset) {
@@ -4257,8 +4257,8 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 	for (reloc = insn_reloc(file, insn);
 	     reloc;
 	     reloc = find_reloc_by_dest_range(file->elf, insn->sec,
-					      reloc->offset + 1,
-					      (insn->offset + insn->len) - (reloc->offset + 1))) {
+					      reloc_offset(reloc) + 1,
+					      (insn->offset + insn->len) - (reloc_offset(reloc) + 1))) {
 
 		/*
 		 * static_call_update() references the trampoline, which
@@ -4341,7 +4341,7 @@ static int validate_ibt_data_reloc(struct objtool_file *file,
 		return 0;
 
 	WARN_FUNC("data relocation to !ENDBR: %s",
-		  reloc->sec->base, reloc->offset,
+		  reloc->sec->base, reloc_offset(reloc),
 		  offstr(dest->sec, dest->offset));
 
 	return 1;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 70c801254566..2b45460225d1 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -246,8 +246,9 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 			if (reloc->sec != rsec)
 				continue;
 
-			if (reloc->offset >= offset && reloc->offset < offset + len) {
-				if (!r || reloc->offset < r->offset)
+			if (reloc_offset(reloc) >= offset &&
+			    reloc_offset(reloc) < offset + len) {
+				if (!r || reloc_offset(reloc) < reloc_offset(r))
 					r = reloc;
 			}
 		}
@@ -830,11 +831,12 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	}
 
 	reloc->sec = rsec;
-	reloc->offset = offset;
 	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
+	reloc->rel.r_offset = offset;
+
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
 
@@ -908,7 +910,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->offset = reloc->rel.r_offset;
 	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
 	reloc->addend = rela ? reloc->rela.r_addend : 0;
 
@@ -1230,7 +1231,6 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	reloc->rel.r_offset = reloc->offset;
 	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 
 	if (rsec->sh.sh_type == SHT_RELA) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2a14da633d56..2070860a099e 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	unsigned long offset;
 	s64 addend;
 	unsigned int type;
 	bool jump_table_start;
@@ -204,6 +203,11 @@ static inline unsigned int reloc_idx(struct reloc *reloc)
 	return reloc - reloc->sec->relocs;
 }
 
+static inline unsigned long reloc_offset(struct reloc *reloc)
+{
+	return reloc->rel.r_offset;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -253,7 +257,7 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
 
 static inline u32 reloc_hash(struct reloc *reloc)
 {
-	return sec_offset_hash(reloc->sec, reloc->offset);
+	return sec_offset_hash(reloc->sec, reloc_offset(reloc));
 }
 
 #endif /* _OBJTOOL_ELF_H */
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 15/22] objtool: Get rid of reloc->type
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (13 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 14/22] objtool: Get rid of reloc->offset Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 16/22] objtool: Get rid of reloc->addend Josh Poimboeuf
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Get the type from the embedded GElf_Rel[a] struct.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/x86/decode.c     |  2 +-
 tools/objtool/arch/x86/special.c    |  4 ++--
 tools/objtool/check.c               | 11 ++++++-----
 tools/objtool/elf.c                 |  6 ++----
 tools/objtool/include/objtool/elf.h | 11 ++++++++++-
 5 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 9ef024fd648c..ffb12e83b238 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -84,7 +84,7 @@ bool arch_pc_relative_reloc(struct reloc *reloc)
 	 * All relocation types where P (the address of the target)
 	 * is included in the computation.
 	 */
-	switch (reloc->type) {
+	switch (reloc_type(reloc)) {
 	case R_X86_64_PC8:
 	case R_X86_64_PC16:
 	case R_X86_64_PC32:
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 7c97b7391279..1a54a249cb50 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -108,7 +108,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	table_offset = text_reloc->addend;
 	table_sec = text_reloc->sym->sec;
 
-	if (text_reloc->type == R_X86_64_PC32)
+	if (reloc_type(text_reloc) == R_X86_64_PC32)
 		table_offset += 4;
 
 	/*
@@ -138,7 +138,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	 * indicates a rare GCC quirk/bug which can leave dead
 	 * code behind.
 	 */
-	if (text_reloc->type == R_X86_64_PC32)
+	if (reloc_type(text_reloc) == R_X86_64_PC32)
 		file->ignore_unreachables = true;
 
 	return rodata_reloc;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 440c326121d4..1d794d15bc53 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -957,7 +957,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 		if (!reloc)
 			return -1;
 
-		reloc->type = addr_size == 8 ? R_ABS64 : R_ABS32;
+		set_reloc_type(reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
 
 		idx++;
 	}
@@ -1353,7 +1353,7 @@ static void annotate_call_site(struct objtool_file *file,
 	 */
 	if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
 		if (reloc) {
-			reloc->type = R_NONE;
+			set_reloc_type(reloc, R_NONE);
 			elf_write_reloc(file->elf, reloc);
 		}
 
@@ -1382,7 +1382,7 @@ static void annotate_call_site(struct objtool_file *file,
 			WARN_INSN(insn, "tail call to __fentry__ !?!?");
 		if (opts.mnop) {
 			if (reloc) {
-				reloc->type = R_NONE;
+				set_reloc_type(reloc, R_NONE);
 				elf_write_reloc(file->elf, reloc);
 			}
 
@@ -1864,7 +1864,7 @@ static int handle_jump_alt(struct objtool_file *file,
 		struct reloc *reloc = insn_reloc(file, orig_insn);
 
 		if (reloc) {
-			reloc->type = R_NONE;
+			set_reloc_type(reloc, R_NONE);
 			elf_write_reloc(file->elf, reloc);
 		}
 		elf_write_insn(file->elf, orig_insn->sec,
@@ -4268,7 +4268,8 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 			continue;
 
 		off = reloc->sym->offset;
-		if (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32)
+		if (reloc_type(reloc) == R_X86_64_PC32 ||
+		    reloc_type(reloc) == R_X86_64_PLT32)
 			off += arch_dest_reloc_offset(reloc->addend);
 		else
 			off += reloc->addend;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 2b45460225d1..be9d24dcdf56 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -541,6 +541,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
 		if (elf_write_reloc(elf, reloc))
 			return -1;
 	}
@@ -831,11 +832,11 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	}
 
 	reloc->sec = rsec;
-	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
 	reloc->rel.r_offset = offset;
+	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
 
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
@@ -910,7 +911,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
 	reloc->addend = rela ? reloc->rela.r_addend : 0;
 
 	return 0;
@@ -1231,8 +1231,6 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-
 	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
 		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2070860a099e..41d2149f8bb8 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -76,7 +76,6 @@ struct reloc {
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
 	s64 addend;
-	unsigned int type;
 	bool jump_table_start;
 };
 
@@ -208,6 +207,16 @@ static inline unsigned long reloc_offset(struct reloc *reloc)
 	return reloc->rel.r_offset;
 }
 
+static inline unsigned int reloc_type(struct reloc *reloc)
+{
+	return GELF_R_TYPE(reloc->rel.r_info);
+}
+
+static inline void set_reloc_type(struct reloc *reloc, int type)
+{
+	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 16/22] objtool: Get rid of reloc->addend
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (14 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 15/22] objtool: Get rid of reloc->type Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 17/22] objtool: Get rid of reloc->jump_table_start Josh Poimboeuf
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Get the addend from the embedded GElf_Rel[a] struct.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 42.10G
- After:  peak heap memory consumption: 40.37G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/x86/decode.c     |  4 +-
 tools/objtool/arch/x86/special.c    |  2 +-
 tools/objtool/check.c               | 69 +++++++++++++++++------------
 tools/objtool/elf.c                 | 10 ++---
 tools/objtool/include/objtool/elf.h |  6 ++-
 tools/objtool/special.c             |  4 +-
 6 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index ffb12e83b238..2e1caabecb18 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -623,11 +623,11 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			if (!immr || strcmp(immr->sym->name, "pv_ops"))
 				break;
 
-			idx = (immr->addend + 8) / sizeof(void *);
+			idx = (reloc_addend(immr) + 8) / sizeof(void *);
 
 			func = disp->sym;
 			if (disp->sym->type == STT_SECTION)
-				func = find_symbol_by_offset(disp->sym->sec, disp->addend);
+				func = find_symbol_by_offset(disp->sym->sec, reloc_addend(disp));
 			if (!func) {
 				WARN("no func for pv_ops[]");
 				return -1;
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 1a54a249cb50..65f48f35b97e 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -105,7 +105,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	    !text_reloc->sym->sec->rodata)
 		return NULL;
 
-	table_offset = text_reloc->addend;
+	table_offset = reloc_addend(text_reloc);
 	table_sec = text_reloc->sym->sec;
 
 	if (reloc_type(text_reloc) == R_X86_64_PC32)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 1d794d15bc53..12a9e6fb3fe7 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -508,7 +508,8 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 
 		func = reloc->sym;
 		if (func->type == STT_SECTION)
-			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
+			func = find_symbol_by_offset(reloc->sym->sec,
+						     reloc_addend(reloc));
 
 		idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 
@@ -582,6 +583,7 @@ static int add_dead_ends(struct objtool_file *file)
 	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
+	s64 addend;
 
 	/*
 	 * Check for manually annotated dead ends.
@@ -591,23 +593,27 @@ static int add_dead_ends(struct objtool_file *file)
 		goto reachable;
 
 	for_each_reloc(rsec, reloc) {
+
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+		addend = reloc_addend(reloc);
+
+		insn = find_insn(file, reloc->sym->sec, addend);
 		if (insn)
 			insn = prev_insn_same_sec(file, insn);
-		else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+		else if (addend == reloc->sym->sec->sh.sh_size) {
 			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find unreachable insn at %s+0x%" PRIx64,
-				     reloc->sym->sec->name, reloc->addend);
+				     reloc->sym->sec->name, addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find unreachable insn at %s+0x%" PRIx64,
-			     reloc->sym->sec->name, reloc->addend);
+			     reloc->sym->sec->name, addend);
 			return -1;
 		}
 
@@ -626,23 +632,27 @@ static int add_dead_ends(struct objtool_file *file)
 		return 0;
 
 	for_each_reloc(rsec, reloc) {
+
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+		addend = reloc_addend(reloc);
+
+		insn = find_insn(file, reloc->sym->sec, addend);
 		if (insn)
 			insn = prev_insn_same_sec(file, insn);
-		else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+		else if (addend == reloc->sym->sec->sh.sh_size) {
 			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find reachable insn at %s+0x%" PRIx64,
-				     reloc->sym->sec->name, reloc->addend);
+				     reloc->sym->sec->name, addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find reachable insn at %s+0x%" PRIx64,
-			     reloc->sym->sec->name, reloc->addend);
+			     reloc->sym->sec->name, addend);
 			return -1;
 		}
 
@@ -1025,7 +1035,7 @@ static void add_ignores(struct objtool_file *file)
 			break;
 
 		case STT_SECTION:
-			func = find_func_by_offset(reloc->sym->sec, reloc->addend);
+			func = find_func_by_offset(reloc->sym->sec, reloc_addend(reloc));
 			if (!func)
 				continue;
 			break;
@@ -1265,7 +1275,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.ignore_alts entry");
 			return -1;
@@ -1541,7 +1551,7 @@ static int add_jump_destinations(struct objtool_file *file)
 			dest_off = arch_jump_destination(insn);
 		} else if (reloc->sym->type == STT_SECTION) {
 			dest_sec = reloc->sym->sec;
-			dest_off = arch_dest_reloc_offset(reloc->addend);
+			dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 		} else if (reloc->sym->retpoline_thunk) {
 			add_retpoline_call(file, insn);
 			continue;
@@ -1558,7 +1568,7 @@ static int add_jump_destinations(struct objtool_file *file)
 		} else if (reloc->sym->sec->idx) {
 			dest_sec = reloc->sym->sec;
 			dest_off = reloc->sym->sym.st_value +
-				   arch_dest_reloc_offset(reloc->addend);
+				   arch_dest_reloc_offset(reloc_addend(reloc));
 		} else {
 			/* non-func asm code jumping to another file */
 			continue;
@@ -1675,7 +1685,7 @@ static int add_call_destinations(struct objtool_file *file)
 			}
 
 		} else if (reloc->sym->type == STT_SECTION) {
-			dest_off = arch_dest_reloc_offset(reloc->addend);
+			dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 			dest = find_call_destination(reloc->sym->sec, dest_off);
 			if (!dest) {
 				WARN_INSN(insn, "can't find call dest symbol at %s+0x%lx",
@@ -2002,10 +2012,10 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 
 		/* Detect function pointers from contiguous objects: */
 		if (reloc->sym->sec == pfunc->sec &&
-		    reloc->addend == pfunc->offset)
+		    reloc_addend(reloc) == pfunc->offset)
 			break;
 
-		dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!dest_insn)
 			break;
 
@@ -2066,7 +2076,7 @@ static struct reloc *find_jump_table(struct objtool_file *file,
 		table_reloc = arch_find_switch_table(file, insn);
 		if (!table_reloc)
 			continue;
-		dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
+		dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc));
 		if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func)
 			continue;
 
@@ -2202,7 +2212,7 @@ static int read_unwind_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("can't find insn for unwind_hints[%d]", i);
 			return -1;
@@ -2265,7 +2275,8 @@ static int read_noendbr_hints(struct objtool_file *file)
 		return 0;
 
 	for_each_reloc(rsec, reloc) {
-		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
+		insn = find_insn(file, reloc->sym->sec,
+				 reloc->sym->offset + reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
 			return -1;
@@ -2293,7 +2304,7 @@ static int read_retpoline_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.retpoline_safe entry");
 			return -1;
@@ -2329,7 +2340,7 @@ static int read_instr_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_end entry");
 			return -1;
@@ -2348,7 +2359,7 @@ static int read_instr_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_begin entry");
 			return -1;
@@ -2376,7 +2387,7 @@ static int read_validate_unret_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_end entry");
 			return -1;
@@ -2407,7 +2418,7 @@ static int read_intra_function_calls(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.intra_function_call entry");
 			return -1;
@@ -3307,7 +3318,7 @@ static inline const char *call_dest_name(struct instruction *insn)
 
 	reloc = insn_reloc(NULL, insn);
 	if (reloc && !strcmp(reloc->sym->name, "pv_ops")) {
-		idx = (reloc->addend / sizeof(void *));
+		idx = (reloc_addend(reloc) / sizeof(void *));
 		snprintf(pvname, sizeof(pvname), "pv_ops[%d]", idx);
 		return pvname;
 	}
@@ -3325,7 +3336,7 @@ static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
 	if (!reloc || strcmp(reloc->sym->name, "pv_ops"))
 		return false;
 
-	idx = (arch_dest_reloc_offset(reloc->addend) / sizeof(void *));
+	idx = (arch_dest_reloc_offset(reloc_addend(reloc)) / sizeof(void *));
 
 	if (file->pv_ops[idx].clean)
 		return true;
@@ -4270,9 +4281,9 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 		off = reloc->sym->offset;
 		if (reloc_type(reloc) == R_X86_64_PC32 ||
 		    reloc_type(reloc) == R_X86_64_PLT32)
-			off += arch_dest_reloc_offset(reloc->addend);
+			off += arch_dest_reloc_offset(reloc_addend(reloc));
 		else
-			off += reloc->addend;
+			off += reloc_addend(reloc);
 
 		dest = find_insn(file, reloc->sym->sec, off);
 		if (!dest)
@@ -4329,7 +4340,7 @@ static int validate_ibt_data_reloc(struct objtool_file *file,
 	struct instruction *dest;
 
 	dest = find_insn(file, reloc->sym->sec,
-			 reloc->sym->offset + reloc->addend);
+			 reloc->sym->offset + reloc_addend(reloc));
 	if (!dest)
 		return 0;
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index be9d24dcdf56..16e019a1762c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -833,10 +833,10 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 
 	reloc->sec = rsec;
 	reloc->sym = sym;
-	reloc->addend = addend;
 
 	reloc->rel.r_offset = offset;
 	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
+	reloc->rela.r_addend = addend;
 
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
@@ -911,8 +911,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->addend = rela ? reloc->rela.r_addend : 0;
-
 	return 0;
 }
 
@@ -1231,12 +1229,10 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	if (rsec->sh.sh_type == SHT_RELA) {
-		reloc->rela.r_addend = reloc->addend;
+	if (rsec->sh.sh_type == SHT_RELA)
 		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
-	} else {
+	else
 		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
-	}
 
 	if (!ret) {
 		WARN_ELF("gelf_update_rela");
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 41d2149f8bb8..be08b32a93ee 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	s64 addend;
 	bool jump_table_start;
 };
 
@@ -217,6 +216,11 @@ static inline void set_reloc_type(struct reloc *reloc, int type)
 	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
 }
 
+static inline s64 reloc_addend(struct reloc *reloc)
+{
+	return reloc->rela.r_addend;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index baa85c31526b..91b1950f5bd8 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -62,7 +62,7 @@ static void reloc_to_sec_off(struct reloc *reloc, struct section **sec,
 			     unsigned long *off)
 {
 	*sec = reloc->sym->sec;
-	*off = reloc->sym->offset + reloc->addend;
+	*off = reloc->sym->offset + reloc_addend(reloc);
 }
 
 static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
@@ -126,7 +126,7 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
 				  sec, offset + entry->key);
 			return -1;
 		}
-		alt->key_addend = key_reloc->addend;
+		alt->key_addend = reloc_addend(key_reloc);
 	}
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 17/22] objtool: Get rid of reloc->jump_table_start
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (15 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 16/22] objtool: Get rid of reloc->addend Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 18/22] objtool: Shrink reloc->sym_reloc_entry Josh Poimboeuf
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Rework the jump table logic slightly so 'jump_table_start' is no longer
needed.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 40.37G
- After:  peak heap memory consumption: 38.64G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 35 +++++++++++++++++++----------
 tools/objtool/include/objtool/elf.h |  1 -
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 12a9e6fb3fe7..3fe6b3657e22 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1988,13 +1988,14 @@ static int add_special_section_alts(struct objtool_file *file)
 }
 
 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
-			    struct reloc *table)
+			  struct reloc *next_table)
 {
-	struct reloc *reloc = table;
-	struct instruction *dest_insn;
-	struct alternative *alt;
 	struct symbol *pfunc = insn_func(insn)->pfunc;
+	struct reloc *table = insn_jump_table(insn);
+	struct instruction *dest_insn;
 	unsigned int prev_offset = 0;
+	struct reloc *reloc = table;
+	struct alternative *alt;
 
 	/*
 	 * Each @reloc is a switch table relocation which points to the target
@@ -2003,7 +2004,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 	for_each_reloc_from(table->sec, reloc) {
 
 		/* Check for the end of the table: */
-		if (reloc != table && reloc->jump_table_start)
+		if (reloc != table && reloc == next_table)
 			break;
 
 		/* Make sure the table entries are consecutive: */
@@ -2118,29 +2119,39 @@ static void mark_func_jump_tables(struct objtool_file *file,
 			continue;
 
 		reloc = find_jump_table(file, func, insn);
-		if (reloc) {
-			reloc->jump_table_start = true;
+		if (reloc)
 			insn->_jump_table = reloc;
-		}
 	}
 }
 
 static int add_func_jump_tables(struct objtool_file *file,
 				  struct symbol *func)
 {
-	struct instruction *insn;
-	int ret;
+	struct instruction *insn, *insn_t1 = NULL, *insn_t2;
+	int ret = 0;
 
 	func_for_each_insn(file, func, insn) {
 		if (!insn_jump_table(insn))
 			continue;
 
-		ret = add_jump_table(file, insn, insn_jump_table(insn));
+		if (!insn_t1) {
+			insn_t1 = insn;
+			continue;
+		}
+
+		insn_t2 = insn;
+
+		ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2));
 		if (ret)
 			return ret;
+
+		insn_t1 = insn_t2;
 	}
 
-	return 0;
+	if (insn_t1)
+		ret = add_jump_table(file, insn_t1, NULL);
+
+	return ret;
 }
 
 /*
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index be08b32a93ee..60686f746c9e 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	bool jump_table_start;
 };
 
 struct elf {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 18/22] objtool: Shrink reloc->sym_reloc_entry
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (16 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 17/22] objtool: Get rid of reloc->jump_table_start Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 19/22] objtool: Shrink elf hash nodes Josh Poimboeuf
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Convert it to a singly-linked list.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 38.64G
- After:  peak heap memory consumption: 36.89G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 9 +++++----
 tools/objtool/include/objtool/elf.h | 4 ++--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 16e019a1762c..4b0de0e56068 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -356,7 +356,6 @@ static void elf_add_symbol(struct elf *elf, struct symbol *sym)
 	struct rb_node *pnode;
 	struct symbol *iter;
 
-	INIT_LIST_HEAD(&sym->reloc_list);
 	INIT_LIST_HEAD(&sym->pv_target);
 	sym->alias = sym;
 
@@ -540,7 +539,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) {
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
 		if (elf_write_reloc(elf, reloc))
 			return -1;
@@ -841,8 +840,9 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
 
-	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+	reloc->sym_next_reloc = sym->relocs;
+	sym->relocs = reloc;
 
 	return reloc;
 }
@@ -960,8 +960,9 @@ static int read_relocs(struct elf *elf)
 				return -1;
 			}
 
-			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+			reloc->sym_next_reloc = sym->relocs;
+			sym->relocs = reloc;
 
 			nr_reloc++;
 		}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 60686f746c9e..7b808ac3156c 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -63,7 +63,7 @@ struct symbol {
 	u8 profiling_func    : 1;
 	u8 warned	     : 1;
 	struct list_head pv_target;
-	struct list_head reloc_list;
+	struct reloc *relocs;
 };
 
 struct reloc {
@@ -74,7 +74,7 @@ struct reloc {
 	};
 	struct section *sec;
 	struct symbol *sym;
-	struct list_head sym_reloc_entry;
+	struct reloc *sym_next_reloc;
 };
 
 struct elf {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 19/22] objtool: Shrink elf hash nodes
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (17 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 18/22] objtool: Shrink reloc->sym_reloc_entry Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 20/22] objtool: Get rid of reloc->rel[a] Josh Poimboeuf
                   ` (2 subsequent siblings)
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Instead of using hlist for the 'struct elf' hashes, use a custom
single-linked list scheme.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 36.89G
- After:  peak heap memory consumption: 35.12G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 52 ++++++++++++++++++++++++-----
 tools/objtool/include/objtool/elf.h | 24 +++++++------
 2 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4b0de0e56068..04038b1324cf 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -32,16 +32,52 @@ static inline u32 str_hash(const char *str)
 #define __elf_table(name)	(elf->name##_hash)
 #define __elf_bits(name)	(elf->name##_bits)
 
-#define elf_hash_add(name, node, key) \
-	hlist_add_head(node, &__elf_table(name)[hash_min(key, __elf_bits(name))])
+#define __elf_table_entry(name, key) \
+	__elf_table(name)[hash_min(key, __elf_bits(name))]
 
-#define elf_hash_for_each_possible(name, obj, member, key) \
-	hlist_for_each_entry(obj, &__elf_table(name)[hash_min(key, __elf_bits(name))], member)
+#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;				\
+})
+
+static inline void __elf_hash_del(struct elf_hash_node *node,
+				  struct elf_hash_node **head)
+{
+	struct elf_hash_node *cur, *prev;
+
+	if (node == *head) {
+		*head = node->next;
+		return;
+	}
+
+	for (prev = NULL, cur = *head; cur; prev = cur, cur = cur->next) {
+		if (cur == node) {
+			prev->next = cur->next;
+			break;
+		}
+	}
+}
+
+#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))
 
 #define elf_alloc_hash(name, size) \
 ({ \
 	__elf_bits(name) = max(10, ilog2(size)); \
-	__elf_table(name) = mmap(NULL, sizeof(struct hlist_head) << __elf_bits(name), \
+	__elf_table(name) = mmap(NULL, sizeof(struct elf_hash_node *) << __elf_bits(name), \
 				 PROT_READ|PROT_WRITE, \
 				 MAP_PRIVATE|MAP_ANON, -1, 0); \
 	if (__elf_table(name) == (void *)-1L) { \
@@ -713,10 +749,10 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 	first_non_local = symtab->sh.sh_info;
 	old = find_symbol_by_index(elf, first_non_local);
 	if (old) {
-		old->idx = new_idx;
 
-		hlist_del(&old->hash);
-		elf_hash_add(symbol, &old->hash, old->idx);
+		elf_hash_del(symbol, &old->hash, old->idx);
+		elf_hash_add(symbol, &old->hash, new_idx);
+		old->idx = new_idx;
 
 		if (elf_update_symbol(elf, symtab, symtab_shndx, old)) {
 			WARN("elf_update_symbol move");
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 7b808ac3156c..03a9040f696c 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -26,10 +26,14 @@
 #define ELF_C_READ_MMAP ELF_C_READ
 #endif
 
+struct elf_hash_node {
+	struct elf_hash_node *next;
+};
+
 struct section {
 	struct list_head list;
-	struct hlist_node hash;
-	struct hlist_node name_hash;
+	struct elf_hash_node hash;
+	struct elf_hash_node name_hash;
 	GElf_Shdr sh;
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
@@ -45,8 +49,8 @@ struct section {
 struct symbol {
 	struct list_head list;
 	struct rb_node node;
-	struct hlist_node hash;
-	struct hlist_node name_hash;
+	struct elf_hash_node hash;
+	struct elf_hash_node name_hash;
 	GElf_Sym sym;
 	struct section *sec;
 	char *name;
@@ -67,7 +71,7 @@ struct symbol {
 };
 
 struct reloc {
-	struct hlist_node hash;
+	struct elf_hash_node hash;
 	union {
 		GElf_Rela rela;
 		GElf_Rel  rel;
@@ -93,11 +97,11 @@ struct elf {
 	int section_name_bits;
 	int reloc_bits;
 
-	struct hlist_head *symbol_hash;
-	struct hlist_head *symbol_name_hash;
-	struct hlist_head *section_hash;
-	struct hlist_head *section_name_hash;
-	struct hlist_head *reloc_hash;
+	struct elf_hash_node **symbol_hash;
+	struct elf_hash_node **symbol_name_hash;
+	struct elf_hash_node **section_hash;
+	struct elf_hash_node **section_name_hash;
+	struct elf_hash_node **reloc_hash;
 
 	struct section *section_data;
 	struct symbol *symbol_data;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 20/22] objtool: Get rid of reloc->rel[a]
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (18 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 19/22] objtool: Shrink elf hash nodes Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 21/22] objtool: Free insns when done Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 22/22] objtool: Skip reading DWARF section data Josh Poimboeuf
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Get the relocation entry info from the underlying rsec->data.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 35.12G
- After:  peak heap memory consumption: 29.93G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 20 +++---
 tools/objtool/elf.c                 | 60 +++---------------
 tools/objtool/include/objtool/elf.h | 94 +++++++++++++++++++++++++----
 3 files changed, 96 insertions(+), 78 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 3fe6b3657e22..65c59b0b1e96 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -967,7 +967,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 		if (!reloc)
 			return -1;
 
-		set_reloc_type(reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
+		set_reloc_type(file->elf, reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
 
 		idx++;
 	}
@@ -1362,10 +1362,8 @@ static void annotate_call_site(struct objtool_file *file,
 	 * noinstr text.
 	 */
 	if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
-		if (reloc) {
-			set_reloc_type(reloc, R_NONE);
-			elf_write_reloc(file->elf, reloc);
-		}
+		if (reloc)
+			set_reloc_type(file->elf, reloc, R_NONE);
 
 		elf_write_insn(file->elf, insn->sec,
 			       insn->offset, insn->len,
@@ -1391,10 +1389,8 @@ static void annotate_call_site(struct objtool_file *file,
 		if (sibling)
 			WARN_INSN(insn, "tail call to __fentry__ !?!?");
 		if (opts.mnop) {
-			if (reloc) {
-				set_reloc_type(reloc, R_NONE);
-				elf_write_reloc(file->elf, reloc);
-			}
+			if (reloc)
+				set_reloc_type(file->elf, reloc, R_NONE);
 
 			elf_write_insn(file->elf, insn->sec,
 				       insn->offset, insn->len,
@@ -1873,10 +1869,8 @@ static int handle_jump_alt(struct objtool_file *file,
 	if (opts.hack_jump_label && special_alt->key_addend & 2) {
 		struct reloc *reloc = insn_reloc(file, orig_insn);
 
-		if (reloc) {
-			set_reloc_type(reloc, R_NONE);
-			elf_write_reloc(file->elf, reloc);
-		}
+		if (reloc)
+			set_reloc_type(file->elf, reloc, R_NONE);
 		elf_write_insn(file->elf, orig_insn->sec,
 			       orig_insn->offset, orig_insn->len,
 			       arch_nop_insn(orig_insn->len));
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 04038b1324cf..54d182ddc4bb 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -575,11 +575,8 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) {
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
-		if (elf_write_reloc(elf, reloc))
-			return -1;
-	}
+	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc)
+		set_reloc_sym(elf, reloc, reloc->sym->idx);
 
 	return 0;
 }
@@ -869,12 +866,10 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	reloc->sec = rsec;
 	reloc->sym = sym;
 
-	reloc->rel.r_offset = offset;
-	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
-	reloc->rela.r_addend = addend;
-
-	if (elf_write_reloc(elf, reloc))
-		return NULL;
+	set_reloc_offset(elf, reloc, offset);
+	set_reloc_sym(elf, reloc, sym->idx);
+	set_reloc_type(elf, reloc, type);
+	set_reloc_addend(elf, reloc, addend);
 
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 	reloc->sym_next_reloc = sym->relocs;
@@ -932,24 +927,6 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
 			      elf_data_rela_type(elf));
 }
 
-static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
-{
-	bool rela = rsec->sh.sh_type == SHT_RELA;
-	void *retp;
-
-	if (rela)
-		retp = gelf_getrela(rsec->data, i, &reloc->rela);
-	else
-		retp = gelf_getrel(rsec->data, i, &reloc->rel);
-
-	if (!retp) {
-		WARN_ELF("gelf_getrela");
-		return -1;
-	}
-
-	return 0;
-}
-
 static int read_relocs(struct elf *elf)
 {
 	unsigned long nr_reloc, max_reloc = 0;
@@ -984,11 +961,8 @@ static int read_relocs(struct elf *elf)
 		for (i = 0; i < sec_num_entries(rsec); i++) {
 			reloc = &rsec->relocs[i];
 
-			if (read_reloc(rsec, i, reloc))
-				return -1;
-
 			reloc->sec = rsec;
-			symndx = GELF_R_SYM(reloc->rel.r_info);
+			symndx = reloc_sym(reloc);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
@@ -1261,26 +1235,6 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 	return 0;
 }
 
-int elf_write_reloc(struct elf *elf, struct reloc *reloc)
-{
-	struct section *rsec = reloc->sec;
-	int ret;
-
-	if (rsec->sh.sh_type == SHT_RELA)
-		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
-	else
-		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
-
-	if (!ret) {
-		WARN_ELF("gelf_update_rela");
-		return -1;
-	}
-
-	mark_sec_changed(elf, rsec, true);
-
-	return 0;
-}
-
 /*
  * When Elf_Scn::sh_size is smaller than the combined Elf_Data::d_size
  * do you:
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 03a9040f696c..c532d70864dc 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -72,10 +72,6 @@ struct symbol {
 
 struct reloc {
 	struct elf_hash_node hash;
-	union {
-		GElf_Rela rela;
-		GElf_Rel  rel;
-	};
 	struct section *sec;
 	struct symbol *sym;
 	struct reloc *sym_next_reloc;
@@ -132,7 +128,6 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn);
-int elf_write_reloc(struct elf *elf, struct reloc *reloc);
 int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
 
@@ -204,24 +199,99 @@ static inline unsigned int reloc_idx(struct reloc *reloc)
 	return reloc - reloc->sec->relocs;
 }
 
-static inline unsigned long reloc_offset(struct reloc *reloc)
+static inline void *reloc_rel(struct reloc *reloc)
 {
-	return reloc->rel.r_offset;
+	struct section *rsec = reloc->sec;
+
+	return rsec->data->d_buf + (reloc_idx(reloc) * rsec->sh.sh_entsize);
 }
 
-static inline unsigned int reloc_type(struct reloc *reloc)
+static inline bool is_32bit_reloc(struct reloc *reloc)
 {
-	return GELF_R_TYPE(reloc->rel.r_info);
+	/*
+	 * Elf32_Rel:   8 bytes
+	 * Elf32_Rela: 12 bytes
+	 * Elf64_Rel:  16 bytes
+	 * Elf64_Rela: 24 bytes
+	 */
+	return reloc->sec->sh.sh_entsize < 16;
 }
 
-static inline void set_reloc_type(struct reloc *reloc, int type)
+#define __get_reloc_field(reloc, field)					\
+({									\
+	is_32bit_reloc(reloc) ?						\
+		((Elf32_Rela *)reloc_rel(reloc))->field :		\
+		((Elf64_Rela *)reloc_rel(reloc))->field;		\
+})
+
+#define __set_reloc_field(reloc, field, val)				\
+({									\
+	if (is_32bit_reloc(reloc))					\
+		((Elf32_Rela *)reloc_rel(reloc))->field = val;		\
+	else								\
+		((Elf64_Rela *)reloc_rel(reloc))->field = val;		\
+})
+
+static inline u64 reloc_offset(struct reloc *reloc)
 {
-	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
+	return __get_reloc_field(reloc, r_offset);
+}
+
+static inline void set_reloc_offset(struct elf *elf, struct reloc *reloc, u64 offset)
+{
+	__set_reloc_field(reloc, r_offset, offset);
+	mark_sec_changed(elf, reloc->sec, true);
 }
 
 static inline s64 reloc_addend(struct reloc *reloc)
 {
-	return reloc->rela.r_addend;
+	return __get_reloc_field(reloc, r_addend);
+}
+
+static inline void set_reloc_addend(struct elf *elf, struct reloc *reloc, s64 addend)
+{
+	__set_reloc_field(reloc, r_addend, addend);
+	mark_sec_changed(elf, reloc->sec, true);
+}
+
+
+static inline unsigned int reloc_sym(struct reloc *reloc)
+{
+	u64 info = __get_reloc_field(reloc, r_info);
+
+	return is_32bit_reloc(reloc) ?
+		ELF32_R_SYM(info) :
+		ELF64_R_SYM(info);
+}
+
+static inline unsigned int reloc_type(struct reloc *reloc)
+{
+	u64 info = __get_reloc_field(reloc, r_info);
+
+	return is_32bit_reloc(reloc) ?
+		ELF32_R_TYPE(info) :
+		ELF64_R_TYPE(info);
+}
+
+static inline void set_reloc_sym(struct elf *elf, struct reloc *reloc, unsigned int sym)
+{
+	u64 info = is_32bit_reloc(reloc) ?
+		ELF32_R_INFO(sym, reloc_type(reloc)) :
+		ELF64_R_INFO(sym, reloc_type(reloc));
+
+	__set_reloc_field(reloc, r_info, info);
+
+	mark_sec_changed(elf, reloc->sec, true);
+}
+static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned int type)
+{
+	u64 info = is_32bit_reloc(reloc) ?
+		ELF32_R_INFO(reloc_sym(reloc), type) :
+		ELF64_R_INFO(reloc_sym(reloc), type);
+
+	__set_reloc_field(reloc, r_info, info);
+
+	mark_sec_changed(elf, reloc->sec, true);
 }
 
 #define for_each_sec(file, sec)						\
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 21/22] objtool: Free insns when done
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (19 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 20/22] objtool: Get rid of reloc->rel[a] Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  2023-05-30 17:21 ` [PATCH 22/22] objtool: Skip reading DWARF section data Josh Poimboeuf
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Free the decoded instructions as they're no longer needed after this
point.  This frees up a big chunk of heap, which will come handy when
skipping the reading of DWARF section data.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 65c59b0b1e96..80d3a97e442b 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -4587,6 +4587,34 @@ static int disas_warned_funcs(struct objtool_file *file)
 	return 0;
 }
 
+struct insn_chunk {
+	void *addr;
+	struct insn_chunk *next;
+};
+
+/*
+ * Reduce peak RSS usage by freeing insns memory before writing the ELF file,
+ * which can trigger more allocations for .debug_* sections whose data hasn't
+ * been read yet.
+ */
+static void free_insns(struct objtool_file *file)
+{
+	struct instruction *insn;
+	struct insn_chunk *chunks = NULL, *chunk;
+
+	for_each_insn(file, insn) {
+		if (!insn->idx) {
+			chunk = malloc(sizeof(*chunk));
+			chunk->addr = insn;
+			chunk->next = chunks;
+			chunks = chunk;
+		}
+	}
+
+	for (chunk = chunks; chunk; chunk = chunk->next)
+		free(chunk->addr);
+}
+
 int check(struct objtool_file *file)
 {
 	int ret, warnings = 0;
@@ -4731,6 +4759,8 @@ int check(struct objtool_file *file)
 		warnings += ret;
 	}
 
+	free_insns(file);
+
 	if (opts.verbose)
 		disas_warned_funcs(file);
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH 22/22] objtool: Skip reading DWARF section data
  2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
                   ` (20 preceding siblings ...)
  2023-05-30 17:21 ` [PATCH 21/22] objtool: Free insns when done Josh Poimboeuf
@ 2023-05-30 17:21 ` Josh Poimboeuf
  2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
  21 siblings, 1 reply; 45+ messages in thread
From: Josh Poimboeuf @ 2023-05-30 17:21 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, Peter Zijlstra, Miroslav Benes

Objtool doesn't use DWARF at all, and the DWARF sections' data take up a
lot of memory.  Skip reading them.

Note this only skips the DWARF base sections, not the rela sections.
The relas are needed because their symbol references may need to be
reindexed if any local symbols get added by elf_create_symbol().

Also note the DWARF data will eventually be read by libelf anyway, when
writing the object file.  But that's fine, the goal here is to reduce
*peak* memory usage, and the previous patch (which freed insn memory)
gave some breathing room.  So the allocation gets shifted to a later
time, resulting in lower peak memory usage.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 29.93G
- After:  peak heap memory consumption: 25.47G

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 54d182ddc4bb..d420b5d2e2b6 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -300,6 +300,11 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
 	return find_reloc_by_dest_range(elf, sec, offset, 1);
 }
 
+static bool is_dwarf_section(struct section *sec)
+{
+	return !strncmp(sec->name, ".debug_", 7);
+}
+
 static int read_sections(struct elf *elf)
 {
 	Elf_Scn *s = NULL;
@@ -350,7 +355,7 @@ static int read_sections(struct elf *elf)
 			return -1;
 		}
 
-		if (sec->sh.sh_size != 0) {
+		if (sec->sh.sh_size != 0 && !is_dwarf_section(sec)) {
 			sec->data = elf_getdata(s, NULL);
 			if (!sec->data) {
 				WARN_ELF("elf_getdata");
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Skip reading DWARF section data
  2023-05-30 17:21 ` [PATCH 22/22] objtool: Skip reading DWARF section data Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     b4c96ef0add5b701eb37be9830a98610e1d9b4a3
Gitweb:        https://git.kernel.org/tip/b4c96ef0add5b701eb37be9830a98610e1d9b4a3
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:14 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:27 -07:00

objtool: Skip reading DWARF section data

Objtool doesn't use DWARF at all, and the DWARF sections' data take up a
lot of memory.  Skip reading them.

Note this only skips the DWARF base sections, not the rela sections.
The relas are needed because their symbol references may need to be
reindexed if any local symbols get added by elf_create_symbol().

Also note the DWARF data will eventually be read by libelf anyway, when
writing the object file.  But that's fine, the goal here is to reduce
*peak* memory usage, and the previous patch (which freed insn memory)
gave some breathing room.  So the allocation gets shifted to a later
time, resulting in lower peak memory usage.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 29.93G
- After:  peak heap memory consumption: 25.47G

Link: https://lore.kernel.org/r/52a9698835861dd35f2ec35c49f96d0bb39fb177.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 54d182d..d420b5d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -300,6 +300,11 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
 	return find_reloc_by_dest_range(elf, sec, offset, 1);
 }
 
+static bool is_dwarf_section(struct section *sec)
+{
+	return !strncmp(sec->name, ".debug_", 7);
+}
+
 static int read_sections(struct elf *elf)
 {
 	Elf_Scn *s = NULL;
@@ -350,7 +355,7 @@ static int read_sections(struct elf *elf)
 			return -1;
 		}
 
-		if (sec->sh.sh_size != 0) {
+		if (sec->sh.sh_size != 0 && !is_dwarf_section(sec)) {
 			sec->data = elf_getdata(s, NULL);
 			if (!sec->data) {
 				WARN_ELF("elf_getdata");

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Free insns when done
  2023-05-30 17:21 ` [PATCH 21/22] objtool: Free insns when done Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     d93b5935fd47007597aed5105a902a10204bc30e
Gitweb:        https://git.kernel.org/tip/d93b5935fd47007597aed5105a902a10204bc30e
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:13 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:27 -07:00

objtool: Free insns when done

Free the decoded instructions as they're no longer needed after this
point.  This frees up a big chunk of heap, which will come handy when
skipping the reading of DWARF section data.

Link: https://lore.kernel.org/r/4d4bca1a0f869de020dac80d91f9acbf6df77eab.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 47ff130..8936a05 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -4596,6 +4596,34 @@ static int disas_warned_funcs(struct objtool_file *file)
 	return 0;
 }
 
+struct insn_chunk {
+	void *addr;
+	struct insn_chunk *next;
+};
+
+/*
+ * Reduce peak RSS usage by freeing insns memory before writing the ELF file,
+ * which can trigger more allocations for .debug_* sections whose data hasn't
+ * been read yet.
+ */
+static void free_insns(struct objtool_file *file)
+{
+	struct instruction *insn;
+	struct insn_chunk *chunks = NULL, *chunk;
+
+	for_each_insn(file, insn) {
+		if (!insn->idx) {
+			chunk = malloc(sizeof(*chunk));
+			chunk->addr = insn;
+			chunk->next = chunks;
+			chunks = chunk;
+		}
+	}
+
+	for (chunk = chunks; chunk; chunk = chunk->next)
+		free(chunk->addr);
+}
+
 int check(struct objtool_file *file)
 {
 	int ret, warnings = 0;
@@ -4742,6 +4770,8 @@ int check(struct objtool_file *file)
 		warnings += ret;
 	}
 
+	free_insns(file);
+
 	if (opts.verbose)
 		disas_warned_funcs(file);
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Shrink elf hash nodes
  2023-05-30 17:21 ` [PATCH 19/22] objtool: Shrink elf hash nodes Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     02b54001066364aee72bc4c802b42a96c6e0dc1f
Gitweb:        https://git.kernel.org/tip/02b54001066364aee72bc4c802b42a96c6e0dc1f
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:11 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:25 -07:00

objtool: Shrink elf hash nodes

Instead of using hlist for the 'struct elf' hashes, use a custom
single-linked list scheme.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 36.89G
- After:  peak heap memory consumption: 35.12G

Link: https://lore.kernel.org/r/6e8cd305ed22e743c30d6e72cfdc1be20fb94cd4.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 52 +++++++++++++++++++++++-----
 tools/objtool/include/objtool/elf.h | 24 +++++++------
 2 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4b0de0e..04038b1 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -32,16 +32,52 @@ static inline u32 str_hash(const char *str)
 #define __elf_table(name)	(elf->name##_hash)
 #define __elf_bits(name)	(elf->name##_bits)
 
-#define elf_hash_add(name, node, key) \
-	hlist_add_head(node, &__elf_table(name)[hash_min(key, __elf_bits(name))])
+#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;				\
+})
+
+static inline void __elf_hash_del(struct elf_hash_node *node,
+				  struct elf_hash_node **head)
+{
+	struct elf_hash_node *cur, *prev;
 
-#define elf_hash_for_each_possible(name, obj, member, key) \
-	hlist_for_each_entry(obj, &__elf_table(name)[hash_min(key, __elf_bits(name))], member)
+	if (node == *head) {
+		*head = node->next;
+		return;
+	}
+
+	for (prev = NULL, cur = *head; cur; prev = cur, cur = cur->next) {
+		if (cur == node) {
+			prev->next = cur->next;
+			break;
+		}
+	}
+}
+
+#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))
 
 #define elf_alloc_hash(name, size) \
 ({ \
 	__elf_bits(name) = max(10, ilog2(size)); \
-	__elf_table(name) = mmap(NULL, sizeof(struct hlist_head) << __elf_bits(name), \
+	__elf_table(name) = mmap(NULL, sizeof(struct elf_hash_node *) << __elf_bits(name), \
 				 PROT_READ|PROT_WRITE, \
 				 MAP_PRIVATE|MAP_ANON, -1, 0); \
 	if (__elf_table(name) == (void *)-1L) { \
@@ -713,10 +749,10 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 	first_non_local = symtab->sh.sh_info;
 	old = find_symbol_by_index(elf, first_non_local);
 	if (old) {
-		old->idx = new_idx;
 
-		hlist_del(&old->hash);
-		elf_hash_add(symbol, &old->hash, old->idx);
+		elf_hash_del(symbol, &old->hash, old->idx);
+		elf_hash_add(symbol, &old->hash, new_idx);
+		old->idx = new_idx;
 
 		if (elf_update_symbol(elf, symtab, symtab_shndx, old)) {
 			WARN("elf_update_symbol move");
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 7b808ac..03a9040 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -26,10 +26,14 @@
 #define ELF_C_READ_MMAP ELF_C_READ
 #endif
 
+struct elf_hash_node {
+	struct elf_hash_node *next;
+};
+
 struct section {
 	struct list_head list;
-	struct hlist_node hash;
-	struct hlist_node name_hash;
+	struct elf_hash_node hash;
+	struct elf_hash_node name_hash;
 	GElf_Shdr sh;
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
@@ -45,8 +49,8 @@ struct section {
 struct symbol {
 	struct list_head list;
 	struct rb_node node;
-	struct hlist_node hash;
-	struct hlist_node name_hash;
+	struct elf_hash_node hash;
+	struct elf_hash_node name_hash;
 	GElf_Sym sym;
 	struct section *sec;
 	char *name;
@@ -67,7 +71,7 @@ struct symbol {
 };
 
 struct reloc {
-	struct hlist_node hash;
+	struct elf_hash_node hash;
 	union {
 		GElf_Rela rela;
 		GElf_Rel  rel;
@@ -93,11 +97,11 @@ struct elf {
 	int section_name_bits;
 	int reloc_bits;
 
-	struct hlist_head *symbol_hash;
-	struct hlist_head *symbol_name_hash;
-	struct hlist_head *section_hash;
-	struct hlist_head *section_name_hash;
-	struct hlist_head *reloc_hash;
+	struct elf_hash_node **symbol_hash;
+	struct elf_hash_node **symbol_name_hash;
+	struct elf_hash_node **section_hash;
+	struct elf_hash_node **section_name_hash;
+	struct elf_hash_node **reloc_hash;
 
 	struct section *section_data;
 	struct symbol *symbol_data;

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->rel[a]
  2023-05-30 17:21 ` [PATCH 20/22] objtool: Get rid of reloc->rel[a] Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     ec24b927c1fbfc91cf7a48276d9fd92072b17d3b
Gitweb:        https://git.kernel.org/tip/ec24b927c1fbfc91cf7a48276d9fd92072b17d3b
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:12 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:26 -07:00

objtool: Get rid of reloc->rel[a]

Get the relocation entry info from the underlying rsec->data.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 35.12G
- After:  peak heap memory consumption: 29.93G

Link: https://lore.kernel.org/r/2be32323de6d8cc73179ee0ff14b71f4e7cefaa0.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 20 ++----
 tools/objtool/elf.c                 | 60 ++----------------
 tools/objtool/include/objtool/elf.h | 94 ++++++++++++++++++++++++----
 3 files changed, 96 insertions(+), 78 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 7fb6467..47ff130 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -968,7 +968,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 		if (!reloc)
 			return -1;
 
-		set_reloc_type(reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
+		set_reloc_type(file->elf, reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
 
 		idx++;
 	}
@@ -1363,10 +1363,8 @@ static void annotate_call_site(struct objtool_file *file,
 	 * noinstr text.
 	 */
 	if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
-		if (reloc) {
-			set_reloc_type(reloc, R_NONE);
-			elf_write_reloc(file->elf, reloc);
-		}
+		if (reloc)
+			set_reloc_type(file->elf, reloc, R_NONE);
 
 		elf_write_insn(file->elf, insn->sec,
 			       insn->offset, insn->len,
@@ -1392,10 +1390,8 @@ static void annotate_call_site(struct objtool_file *file,
 		if (sibling)
 			WARN_INSN(insn, "tail call to __fentry__ !?!?");
 		if (opts.mnop) {
-			if (reloc) {
-				set_reloc_type(reloc, R_NONE);
-				elf_write_reloc(file->elf, reloc);
-			}
+			if (reloc)
+				set_reloc_type(file->elf, reloc, R_NONE);
 
 			elf_write_insn(file->elf, insn->sec,
 				       insn->offset, insn->len,
@@ -1874,10 +1870,8 @@ static int handle_jump_alt(struct objtool_file *file,
 	if (opts.hack_jump_label && special_alt->key_addend & 2) {
 		struct reloc *reloc = insn_reloc(file, orig_insn);
 
-		if (reloc) {
-			set_reloc_type(reloc, R_NONE);
-			elf_write_reloc(file->elf, reloc);
-		}
+		if (reloc)
+			set_reloc_type(file->elf, reloc, R_NONE);
 		elf_write_insn(file->elf, orig_insn->sec,
 			       orig_insn->offset, orig_insn->len,
 			       arch_nop_insn(orig_insn->len));
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 04038b1..54d182d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -575,11 +575,8 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) {
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
-		if (elf_write_reloc(elf, reloc))
-			return -1;
-	}
+	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc)
+		set_reloc_sym(elf, reloc, reloc->sym->idx);
 
 	return 0;
 }
@@ -869,12 +866,10 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	reloc->sec = rsec;
 	reloc->sym = sym;
 
-	reloc->rel.r_offset = offset;
-	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
-	reloc->rela.r_addend = addend;
-
-	if (elf_write_reloc(elf, reloc))
-		return NULL;
+	set_reloc_offset(elf, reloc, offset);
+	set_reloc_sym(elf, reloc, sym->idx);
+	set_reloc_type(elf, reloc, type);
+	set_reloc_addend(elf, reloc, addend);
 
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 	reloc->sym_next_reloc = sym->relocs;
@@ -932,24 +927,6 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
 			      elf_data_rela_type(elf));
 }
 
-static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
-{
-	bool rela = rsec->sh.sh_type == SHT_RELA;
-	void *retp;
-
-	if (rela)
-		retp = gelf_getrela(rsec->data, i, &reloc->rela);
-	else
-		retp = gelf_getrel(rsec->data, i, &reloc->rel);
-
-	if (!retp) {
-		WARN_ELF("gelf_getrela");
-		return -1;
-	}
-
-	return 0;
-}
-
 static int read_relocs(struct elf *elf)
 {
 	unsigned long nr_reloc, max_reloc = 0;
@@ -984,11 +961,8 @@ static int read_relocs(struct elf *elf)
 		for (i = 0; i < sec_num_entries(rsec); i++) {
 			reloc = &rsec->relocs[i];
 
-			if (read_reloc(rsec, i, reloc))
-				return -1;
-
 			reloc->sec = rsec;
-			symndx = GELF_R_SYM(reloc->rel.r_info);
+			symndx = reloc_sym(reloc);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
@@ -1261,26 +1235,6 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 	return 0;
 }
 
-int elf_write_reloc(struct elf *elf, struct reloc *reloc)
-{
-	struct section *rsec = reloc->sec;
-	int ret;
-
-	if (rsec->sh.sh_type == SHT_RELA)
-		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
-	else
-		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
-
-	if (!ret) {
-		WARN_ELF("gelf_update_rela");
-		return -1;
-	}
-
-	mark_sec_changed(elf, rsec, true);
-
-	return 0;
-}
-
 /*
  * When Elf_Scn::sh_size is smaller than the combined Elf_Data::d_size
  * do you:
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 03a9040..c532d70 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -72,10 +72,6 @@ struct symbol {
 
 struct reloc {
 	struct elf_hash_node hash;
-	union {
-		GElf_Rela rela;
-		GElf_Rel  rel;
-	};
 	struct section *sec;
 	struct symbol *sym;
 	struct reloc *sym_next_reloc;
@@ -132,7 +128,6 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn);
-int elf_write_reloc(struct elf *elf, struct reloc *reloc);
 int elf_write(struct elf *elf);
 void elf_close(struct elf *elf);
 
@@ -204,24 +199,99 @@ static inline unsigned int reloc_idx(struct reloc *reloc)
 	return reloc - reloc->sec->relocs;
 }
 
-static inline unsigned long reloc_offset(struct reloc *reloc)
+static inline void *reloc_rel(struct reloc *reloc)
 {
-	return reloc->rel.r_offset;
+	struct section *rsec = reloc->sec;
+
+	return rsec->data->d_buf + (reloc_idx(reloc) * rsec->sh.sh_entsize);
 }
 
-static inline unsigned int reloc_type(struct reloc *reloc)
+static inline bool is_32bit_reloc(struct reloc *reloc)
 {
-	return GELF_R_TYPE(reloc->rel.r_info);
+	/*
+	 * Elf32_Rel:   8 bytes
+	 * Elf32_Rela: 12 bytes
+	 * Elf64_Rel:  16 bytes
+	 * Elf64_Rela: 24 bytes
+	 */
+	return reloc->sec->sh.sh_entsize < 16;
 }
 
-static inline void set_reloc_type(struct reloc *reloc, int type)
+#define __get_reloc_field(reloc, field)					\
+({									\
+	is_32bit_reloc(reloc) ?						\
+		((Elf32_Rela *)reloc_rel(reloc))->field :		\
+		((Elf64_Rela *)reloc_rel(reloc))->field;		\
+})
+
+#define __set_reloc_field(reloc, field, val)				\
+({									\
+	if (is_32bit_reloc(reloc))					\
+		((Elf32_Rela *)reloc_rel(reloc))->field = val;		\
+	else								\
+		((Elf64_Rela *)reloc_rel(reloc))->field = val;		\
+})
+
+static inline u64 reloc_offset(struct reloc *reloc)
 {
-	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
+	return __get_reloc_field(reloc, r_offset);
+}
+
+static inline void set_reloc_offset(struct elf *elf, struct reloc *reloc, u64 offset)
+{
+	__set_reloc_field(reloc, r_offset, offset);
+	mark_sec_changed(elf, reloc->sec, true);
 }
 
 static inline s64 reloc_addend(struct reloc *reloc)
 {
-	return reloc->rela.r_addend;
+	return __get_reloc_field(reloc, r_addend);
+}
+
+static inline void set_reloc_addend(struct elf *elf, struct reloc *reloc, s64 addend)
+{
+	__set_reloc_field(reloc, r_addend, addend);
+	mark_sec_changed(elf, reloc->sec, true);
+}
+
+
+static inline unsigned int reloc_sym(struct reloc *reloc)
+{
+	u64 info = __get_reloc_field(reloc, r_info);
+
+	return is_32bit_reloc(reloc) ?
+		ELF32_R_SYM(info) :
+		ELF64_R_SYM(info);
+}
+
+static inline unsigned int reloc_type(struct reloc *reloc)
+{
+	u64 info = __get_reloc_field(reloc, r_info);
+
+	return is_32bit_reloc(reloc) ?
+		ELF32_R_TYPE(info) :
+		ELF64_R_TYPE(info);
+}
+
+static inline void set_reloc_sym(struct elf *elf, struct reloc *reloc, unsigned int sym)
+{
+	u64 info = is_32bit_reloc(reloc) ?
+		ELF32_R_INFO(sym, reloc_type(reloc)) :
+		ELF64_R_INFO(sym, reloc_type(reloc));
+
+	__set_reloc_field(reloc, r_info, info);
+
+	mark_sec_changed(elf, reloc->sec, true);
+}
+static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned int type)
+{
+	u64 info = is_32bit_reloc(reloc) ?
+		ELF32_R_INFO(reloc_sym(reloc), type) :
+		ELF64_R_INFO(reloc_sym(reloc), type);
+
+	__set_reloc_field(reloc, r_info, info);
+
+	mark_sec_changed(elf, reloc->sec, true);
 }
 
 #define for_each_sec(file, sec)						\

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Shrink reloc->sym_reloc_entry
  2023-05-30 17:21 ` [PATCH 18/22] objtool: Shrink reloc->sym_reloc_entry Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     890f10a433f51f95eccaec13d46dde769ccc113b
Gitweb:        https://git.kernel.org/tip/890f10a433f51f95eccaec13d46dde769ccc113b
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:10 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:25 -07:00

objtool: Shrink reloc->sym_reloc_entry

Convert it to a singly-linked list.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 38.64G
- After:  peak heap memory consumption: 36.89G

Link: https://lore.kernel.org/r/a51f0a6f9bbf2494d5a3a449807307e78a940988.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 |  9 +++++----
 tools/objtool/include/objtool/elf.h |  4 ++--
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 16e019a..4b0de0e 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -356,7 +356,6 @@ static void elf_add_symbol(struct elf *elf, struct symbol *sym)
 	struct rb_node *pnode;
 	struct symbol *iter;
 
-	INIT_LIST_HEAD(&sym->reloc_list);
 	INIT_LIST_HEAD(&sym->pv_target);
 	sym->alias = sym;
 
@@ -540,7 +539,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+	for (reloc = sym->relocs; reloc; reloc = reloc->sym_next_reloc) {
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
 		if (elf_write_reloc(elf, reloc))
 			return -1;
@@ -841,8 +840,9 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
 
-	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+	reloc->sym_next_reloc = sym->relocs;
+	sym->relocs = reloc;
 
 	return reloc;
 }
@@ -960,8 +960,9 @@ static int read_relocs(struct elf *elf)
 				return -1;
 			}
 
-			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+			reloc->sym_next_reloc = sym->relocs;
+			sym->relocs = reloc;
 
 			nr_reloc++;
 		}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 60686f7..7b808ac 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -63,7 +63,7 @@ struct symbol {
 	u8 profiling_func    : 1;
 	u8 warned	     : 1;
 	struct list_head pv_target;
-	struct list_head reloc_list;
+	struct reloc *relocs;
 };
 
 struct reloc {
@@ -74,7 +74,7 @@ struct reloc {
 	};
 	struct section *sec;
 	struct symbol *sym;
-	struct list_head sym_reloc_entry;
+	struct reloc *sym_next_reloc;
 };
 
 struct elf {

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->jump_table_start
  2023-05-30 17:21 ` [PATCH 17/22] objtool: Get rid of reloc->jump_table_start Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     be2f0b1e12644c956a347d7fde93c2ffe9cdb1af
Gitweb:        https://git.kernel.org/tip/be2f0b1e12644c956a347d7fde93c2ffe9cdb1af
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:09 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:24 -07:00

objtool: Get rid of reloc->jump_table_start

Rework the jump table logic slightly so 'jump_table_start' is no longer
needed.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 40.37G
- After:  peak heap memory consumption: 38.64G

Link: https://lore.kernel.org/r/e1602ed8a6171ada3cfac0bd8449892ec82bd188.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 35 ++++++++++++++++++----------
 tools/objtool/include/objtool/elf.h |  1 +-
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 745487d..7fb6467 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1989,13 +1989,14 @@ out:
 }
 
 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
-			    struct reloc *table)
+			  struct reloc *next_table)
 {
-	struct reloc *reloc = table;
-	struct instruction *dest_insn;
-	struct alternative *alt;
 	struct symbol *pfunc = insn_func(insn)->pfunc;
+	struct reloc *table = insn_jump_table(insn);
+	struct instruction *dest_insn;
 	unsigned int prev_offset = 0;
+	struct reloc *reloc = table;
+	struct alternative *alt;
 
 	/*
 	 * Each @reloc is a switch table relocation which points to the target
@@ -2004,7 +2005,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 	for_each_reloc_from(table->sec, reloc) {
 
 		/* Check for the end of the table: */
-		if (reloc != table && reloc->jump_table_start)
+		if (reloc != table && reloc == next_table)
 			break;
 
 		/* Make sure the table entries are consecutive: */
@@ -2119,29 +2120,39 @@ static void mark_func_jump_tables(struct objtool_file *file,
 			continue;
 
 		reloc = find_jump_table(file, func, insn);
-		if (reloc) {
-			reloc->jump_table_start = true;
+		if (reloc)
 			insn->_jump_table = reloc;
-		}
 	}
 }
 
 static int add_func_jump_tables(struct objtool_file *file,
 				  struct symbol *func)
 {
-	struct instruction *insn;
-	int ret;
+	struct instruction *insn, *insn_t1 = NULL, *insn_t2;
+	int ret = 0;
 
 	func_for_each_insn(file, func, insn) {
 		if (!insn_jump_table(insn))
 			continue;
 
-		ret = add_jump_table(file, insn, insn_jump_table(insn));
+		if (!insn_t1) {
+			insn_t1 = insn;
+			continue;
+		}
+
+		insn_t2 = insn;
+
+		ret = add_jump_table(file, insn_t1, insn_jump_table(insn_t2));
 		if (ret)
 			return ret;
+
+		insn_t1 = insn_t2;
 	}
 
-	return 0;
+	if (insn_t1)
+		ret = add_jump_table(file, insn_t1, NULL);
+
+	return ret;
 }
 
 /*
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index be08b32..60686f7 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	bool jump_table_start;
 };
 
 struct elf {

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->addend
  2023-05-30 17:21 ` [PATCH 16/22] objtool: Get rid of reloc->addend Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     0696b6e314dbe4bd2f24d5e749469f57ea095a9f
Gitweb:        https://git.kernel.org/tip/0696b6e314dbe4bd2f24d5e749469f57ea095a9f
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:08 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:23 -07:00

objtool: Get rid of reloc->addend

Get the addend from the embedded GElf_Rel[a] struct.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 42.10G
- After:  peak heap memory consumption: 40.37G

Link: https://lore.kernel.org/r/ad2354f95d9ddd86094e3f7687acfa0750657784.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/x86/decode.c     |  4 +-
 tools/objtool/arch/x86/special.c    |  2 +-
 tools/objtool/check.c               | 69 ++++++++++++++++------------
 tools/objtool/elf.c                 | 10 +---
 tools/objtool/include/objtool/elf.h |  6 +-
 tools/objtool/special.c             |  4 +-
 6 files changed, 53 insertions(+), 42 deletions(-)

diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index ffb12e8..2e1caab 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -623,11 +623,11 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			if (!immr || strcmp(immr->sym->name, "pv_ops"))
 				break;
 
-			idx = (immr->addend + 8) / sizeof(void *);
+			idx = (reloc_addend(immr) + 8) / sizeof(void *);
 
 			func = disp->sym;
 			if (disp->sym->type == STT_SECTION)
-				func = find_symbol_by_offset(disp->sym->sec, disp->addend);
+				func = find_symbol_by_offset(disp->sym->sec, reloc_addend(disp));
 			if (!func) {
 				WARN("no func for pv_ops[]");
 				return -1;
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 1a54a24..65f48f3 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -105,7 +105,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	    !text_reloc->sym->sec->rodata)
 		return NULL;
 
-	table_offset = text_reloc->addend;
+	table_offset = reloc_addend(text_reloc);
 	table_sec = text_reloc->sym->sec;
 
 	if (reloc_type(text_reloc) == R_X86_64_PC32)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 04b4152..745487d 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -509,7 +509,8 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 
 		func = reloc->sym;
 		if (func->type == STT_SECTION)
-			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
+			func = find_symbol_by_offset(reloc->sym->sec,
+						     reloc_addend(reloc));
 
 		idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 
@@ -583,6 +584,7 @@ static int add_dead_ends(struct objtool_file *file)
 	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
+	s64 addend;
 
 	/*
 	 * Check for manually annotated dead ends.
@@ -592,23 +594,27 @@ static int add_dead_ends(struct objtool_file *file)
 		goto reachable;
 
 	for_each_reloc(rsec, reloc) {
+
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+		addend = reloc_addend(reloc);
+
+		insn = find_insn(file, reloc->sym->sec, addend);
 		if (insn)
 			insn = prev_insn_same_sec(file, insn);
-		else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+		else if (addend == reloc->sym->sec->sh.sh_size) {
 			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find unreachable insn at %s+0x%" PRIx64,
-				     reloc->sym->sec->name, reloc->addend);
+				     reloc->sym->sec->name, addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find unreachable insn at %s+0x%" PRIx64,
-			     reloc->sym->sec->name, reloc->addend);
+			     reloc->sym->sec->name, addend);
 			return -1;
 		}
 
@@ -627,23 +633,27 @@ reachable:
 		return 0;
 
 	for_each_reloc(rsec, reloc) {
+
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+		addend = reloc_addend(reloc);
+
+		insn = find_insn(file, reloc->sym->sec, addend);
 		if (insn)
 			insn = prev_insn_same_sec(file, insn);
-		else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+		else if (addend == reloc->sym->sec->sh.sh_size) {
 			insn = find_last_insn(file, reloc->sym->sec);
 			if (!insn) {
 				WARN("can't find reachable insn at %s+0x%" PRIx64,
-				     reloc->sym->sec->name, reloc->addend);
+				     reloc->sym->sec->name, addend);
 				return -1;
 			}
 		} else {
 			WARN("can't find reachable insn at %s+0x%" PRIx64,
-			     reloc->sym->sec->name, reloc->addend);
+			     reloc->sym->sec->name, addend);
 			return -1;
 		}
 
@@ -1026,7 +1036,7 @@ static void add_ignores(struct objtool_file *file)
 			break;
 
 		case STT_SECTION:
-			func = find_func_by_offset(reloc->sym->sec, reloc->addend);
+			func = find_func_by_offset(reloc->sym->sec, reloc_addend(reloc));
 			if (!func)
 				continue;
 			break;
@@ -1266,7 +1276,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.ignore_alts entry");
 			return -1;
@@ -1542,7 +1552,7 @@ static int add_jump_destinations(struct objtool_file *file)
 			dest_off = arch_jump_destination(insn);
 		} else if (reloc->sym->type == STT_SECTION) {
 			dest_sec = reloc->sym->sec;
-			dest_off = arch_dest_reloc_offset(reloc->addend);
+			dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 		} else if (reloc->sym->retpoline_thunk) {
 			add_retpoline_call(file, insn);
 			continue;
@@ -1559,7 +1569,7 @@ static int add_jump_destinations(struct objtool_file *file)
 		} else if (reloc->sym->sec->idx) {
 			dest_sec = reloc->sym->sec;
 			dest_off = reloc->sym->sym.st_value +
-				   arch_dest_reloc_offset(reloc->addend);
+				   arch_dest_reloc_offset(reloc_addend(reloc));
 		} else {
 			/* non-func asm code jumping to another file */
 			continue;
@@ -1676,7 +1686,7 @@ static int add_call_destinations(struct objtool_file *file)
 			}
 
 		} else if (reloc->sym->type == STT_SECTION) {
-			dest_off = arch_dest_reloc_offset(reloc->addend);
+			dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
 			dest = find_call_destination(reloc->sym->sec, dest_off);
 			if (!dest) {
 				WARN_INSN(insn, "can't find call dest symbol at %s+0x%lx",
@@ -2003,10 +2013,10 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 
 		/* Detect function pointers from contiguous objects: */
 		if (reloc->sym->sec == pfunc->sec &&
-		    reloc->addend == pfunc->offset)
+		    reloc_addend(reloc) == pfunc->offset)
 			break;
 
-		dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!dest_insn)
 			break;
 
@@ -2067,7 +2077,7 @@ static struct reloc *find_jump_table(struct objtool_file *file,
 		table_reloc = arch_find_switch_table(file, insn);
 		if (!table_reloc)
 			continue;
-		dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
+		dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc));
 		if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func)
 			continue;
 
@@ -2203,7 +2213,7 @@ static int read_unwind_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("can't find insn for unwind_hints[%d]", i);
 			return -1;
@@ -2271,7 +2281,8 @@ static int read_noendbr_hints(struct objtool_file *file)
 		return 0;
 
 	for_each_reloc(rsec, reloc) {
-		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
+		insn = find_insn(file, reloc->sym->sec,
+				 reloc->sym->offset + reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
 			return -1;
@@ -2299,7 +2310,7 @@ static int read_retpoline_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.retpoline_safe entry");
 			return -1;
@@ -2335,7 +2346,7 @@ static int read_instr_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_end entry");
 			return -1;
@@ -2354,7 +2365,7 @@ static int read_instr_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_begin entry");
 			return -1;
@@ -2382,7 +2393,7 @@ static int read_validate_unret_hints(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.instr_end entry");
 			return -1;
@@ -2413,7 +2424,7 @@ static int read_intra_function_calls(struct objtool_file *file)
 			return -1;
 		}
 
-		insn = find_insn(file, reloc->sym->sec, reloc->addend);
+		insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
 		if (!insn) {
 			WARN("bad .discard.intra_function_call entry");
 			return -1;
@@ -3317,7 +3328,7 @@ static inline const char *call_dest_name(struct instruction *insn)
 
 	reloc = insn_reloc(NULL, insn);
 	if (reloc && !strcmp(reloc->sym->name, "pv_ops")) {
-		idx = (reloc->addend / sizeof(void *));
+		idx = (reloc_addend(reloc) / sizeof(void *));
 		snprintf(pvname, sizeof(pvname), "pv_ops[%d]", idx);
 		return pvname;
 	}
@@ -3335,7 +3346,7 @@ static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
 	if (!reloc || strcmp(reloc->sym->name, "pv_ops"))
 		return false;
 
-	idx = (arch_dest_reloc_offset(reloc->addend) / sizeof(void *));
+	idx = (arch_dest_reloc_offset(reloc_addend(reloc)) / sizeof(void *));
 
 	if (file->pv_ops[idx].clean)
 		return true;
@@ -4279,9 +4290,9 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 		off = reloc->sym->offset;
 		if (reloc_type(reloc) == R_X86_64_PC32 ||
 		    reloc_type(reloc) == R_X86_64_PLT32)
-			off += arch_dest_reloc_offset(reloc->addend);
+			off += arch_dest_reloc_offset(reloc_addend(reloc));
 		else
-			off += reloc->addend;
+			off += reloc_addend(reloc);
 
 		dest = find_insn(file, reloc->sym->sec, off);
 		if (!dest)
@@ -4338,7 +4349,7 @@ static int validate_ibt_data_reloc(struct objtool_file *file,
 	struct instruction *dest;
 
 	dest = find_insn(file, reloc->sym->sec,
-			 reloc->sym->offset + reloc->addend);
+			 reloc->sym->offset + reloc_addend(reloc));
 	if (!dest)
 		return 0;
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index be9d24d..16e019a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -833,10 +833,10 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 
 	reloc->sec = rsec;
 	reloc->sym = sym;
-	reloc->addend = addend;
 
 	reloc->rel.r_offset = offset;
 	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
+	reloc->rela.r_addend = addend;
 
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
@@ -911,8 +911,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->addend = rela ? reloc->rela.r_addend : 0;
-
 	return 0;
 }
 
@@ -1231,12 +1229,10 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	if (rsec->sh.sh_type == SHT_RELA) {
-		reloc->rela.r_addend = reloc->addend;
+	if (rsec->sh.sh_type == SHT_RELA)
 		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
-	} else {
+	else
 		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
-	}
 
 	if (!ret) {
 		WARN_ELF("gelf_update_rela");
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 41d2149..be08b32 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	s64 addend;
 	bool jump_table_start;
 };
 
@@ -217,6 +216,11 @@ static inline void set_reloc_type(struct reloc *reloc, int type)
 	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
 }
 
+static inline s64 reloc_addend(struct reloc *reloc)
+{
+	return reloc->rela.r_addend;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index baa85c3..91b1950 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -62,7 +62,7 @@ static void reloc_to_sec_off(struct reloc *reloc, struct section **sec,
 			     unsigned long *off)
 {
 	*sec = reloc->sym->sec;
-	*off = reloc->sym->offset + reloc->addend;
+	*off = reloc->sym->offset + reloc_addend(reloc);
 }
 
 static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
@@ -126,7 +126,7 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
 				  sec, offset + entry->key);
 			return -1;
 		}
-		alt->key_addend = key_reloc->addend;
+		alt->key_addend = reloc_addend(key_reloc);
 	}
 
 	return 0;

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->type
  2023-05-30 17:21 ` [PATCH 15/22] objtool: Get rid of reloc->type Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     fcee899d2794319c9dbeb7b877b0c4ac92f5dd16
Gitweb:        https://git.kernel.org/tip/fcee899d2794319c9dbeb7b877b0c4ac92f5dd16
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:07 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:22 -07:00

objtool: Get rid of reloc->type

Get the type from the embedded GElf_Rel[a] struct.

Link: https://lore.kernel.org/r/d1c1f8da31e4f052a2478aea585fcf355cacc53a.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/x86/decode.c     |  2 +-
 tools/objtool/arch/x86/special.c    |  4 ++--
 tools/objtool/check.c               | 11 ++++++-----
 tools/objtool/elf.c                 |  6 ++----
 tools/objtool/include/objtool/elf.h | 11 ++++++++++-
 5 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 9ef024f..ffb12e8 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -84,7 +84,7 @@ bool arch_pc_relative_reloc(struct reloc *reloc)
 	 * All relocation types where P (the address of the target)
 	 * is included in the computation.
 	 */
-	switch (reloc->type) {
+	switch (reloc_type(reloc)) {
 	case R_X86_64_PC8:
 	case R_X86_64_PC16:
 	case R_X86_64_PC32:
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 7c97b73..1a54a24 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -108,7 +108,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	table_offset = text_reloc->addend;
 	table_sec = text_reloc->sym->sec;
 
-	if (text_reloc->type == R_X86_64_PC32)
+	if (reloc_type(text_reloc) == R_X86_64_PC32)
 		table_offset += 4;
 
 	/*
@@ -138,7 +138,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
 	 * indicates a rare GCC quirk/bug which can leave dead
 	 * code behind.
 	 */
-	if (text_reloc->type == R_X86_64_PC32)
+	if (reloc_type(text_reloc) == R_X86_64_PC32)
 		file->ignore_unreachables = true;
 
 	return rodata_reloc;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e06ffad..04b4152 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -958,7 +958,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 		if (!reloc)
 			return -1;
 
-		reloc->type = addr_size == 8 ? R_ABS64 : R_ABS32;
+		set_reloc_type(reloc, addr_size == 8 ? R_ABS64 : R_ABS32);
 
 		idx++;
 	}
@@ -1354,7 +1354,7 @@ static void annotate_call_site(struct objtool_file *file,
 	 */
 	if (opts.hack_noinstr && insn->sec->noinstr && sym->profiling_func) {
 		if (reloc) {
-			reloc->type = R_NONE;
+			set_reloc_type(reloc, R_NONE);
 			elf_write_reloc(file->elf, reloc);
 		}
 
@@ -1383,7 +1383,7 @@ static void annotate_call_site(struct objtool_file *file,
 			WARN_INSN(insn, "tail call to __fentry__ !?!?");
 		if (opts.mnop) {
 			if (reloc) {
-				reloc->type = R_NONE;
+				set_reloc_type(reloc, R_NONE);
 				elf_write_reloc(file->elf, reloc);
 			}
 
@@ -1865,7 +1865,7 @@ static int handle_jump_alt(struct objtool_file *file,
 		struct reloc *reloc = insn_reloc(file, orig_insn);
 
 		if (reloc) {
-			reloc->type = R_NONE;
+			set_reloc_type(reloc, R_NONE);
 			elf_write_reloc(file->elf, reloc);
 		}
 		elf_write_insn(file->elf, orig_insn->sec,
@@ -4277,7 +4277,8 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 			continue;
 
 		off = reloc->sym->offset;
-		if (reloc->type == R_X86_64_PC32 || reloc->type == R_X86_64_PLT32)
+		if (reloc_type(reloc) == R_X86_64_PC32 ||
+		    reloc_type(reloc) == R_X86_64_PLT32)
 			off += arch_dest_reloc_offset(reloc->addend);
 		else
 			off += reloc->addend;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 2b45460..be9d24d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -541,6 +541,7 @@ static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc_type(reloc));
 		if (elf_write_reloc(elf, reloc))
 			return -1;
 	}
@@ -831,11 +832,11 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	}
 
 	reloc->sec = rsec;
-	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
 	reloc->rel.r_offset = offset;
+	reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
 
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
@@ -910,7 +911,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
 	reloc->addend = rela ? reloc->rela.r_addend : 0;
 
 	return 0;
@@ -1231,8 +1231,6 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-
 	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
 		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2070860..41d2149 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -76,7 +76,6 @@ struct reloc {
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
 	s64 addend;
-	unsigned int type;
 	bool jump_table_start;
 };
 
@@ -208,6 +207,16 @@ static inline unsigned long reloc_offset(struct reloc *reloc)
 	return reloc->rel.r_offset;
 }
 
+static inline unsigned int reloc_type(struct reloc *reloc)
+{
+	return GELF_R_TYPE(reloc->rel.r_info);
+}
+
+static inline void set_reloc_type(struct reloc *reloc, int type)
+{
+	reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->offset
  2023-05-30 17:21 ` [PATCH 14/22] objtool: Get rid of reloc->offset Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     e4cbb9b81f1f7519c7ae3abda09cb15794022952
Gitweb:        https://git.kernel.org/tip/e4cbb9b81f1f7519c7ae3abda09cb15794022952
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:06 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:21 -07:00

objtool: Get rid of reloc->offset

Get the offset from the embedded GElf_Rel[a] struct.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 43.83G
- After:  peak heap memory consumption: 42.10G

Link: https://lore.kernel.org/r/2b9ec01178baa346a99522710bf2e82159412e3a.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 14 +++++++-------
 tools/objtool/elf.c                 | 10 +++++-----
 tools/objtool/include/objtool/elf.h |  8 ++++++--
 3 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e21138d..e06ffad 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -511,11 +511,11 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 		if (func->type == STT_SECTION)
 			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
 
-		idx = (reloc->offset - sym->offset) / sizeof(unsigned long);
+		idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 
 		objtool_pv_add(file, idx, func);
 
-		off = reloc->offset + 1;
+		off = reloc_offset(reloc) + 1;
 		if (off > end)
 			break;
 	}
@@ -1998,7 +1998,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 			break;
 
 		/* Make sure the table entries are consecutive: */
-		if (prev_offset && reloc->offset != prev_offset + 8)
+		if (prev_offset && reloc_offset(reloc) != prev_offset + 8)
 			break;
 
 		/* Detect function pointers from contiguous objects: */
@@ -2023,7 +2023,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 		alt->insn = dest_insn;
 		alt->next = insn->alts;
 		insn->alts = alt;
-		prev_offset = reloc->offset;
+		prev_offset = reloc_offset(reloc);
 	}
 
 	if (!prev_offset) {
@@ -4266,8 +4266,8 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
 	for (reloc = insn_reloc(file, insn);
 	     reloc;
 	     reloc = find_reloc_by_dest_range(file->elf, insn->sec,
-					      reloc->offset + 1,
-					      (insn->offset + insn->len) - (reloc->offset + 1))) {
+					      reloc_offset(reloc) + 1,
+					      (insn->offset + insn->len) - (reloc_offset(reloc) + 1))) {
 
 		/*
 		 * static_call_update() references the trampoline, which
@@ -4350,7 +4350,7 @@ static int validate_ibt_data_reloc(struct objtool_file *file,
 		return 0;
 
 	WARN_FUNC("data relocation to !ENDBR: %s",
-		  reloc->sec->base, reloc->offset,
+		  reloc->sec->base, reloc_offset(reloc),
 		  offstr(dest->sec, dest->offset));
 
 	return 1;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 70c8012..2b45460 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -246,8 +246,9 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 			if (reloc->sec != rsec)
 				continue;
 
-			if (reloc->offset >= offset && reloc->offset < offset + len) {
-				if (!r || reloc->offset < r->offset)
+			if (reloc_offset(reloc) >= offset &&
+			    reloc_offset(reloc) < offset + len) {
+				if (!r || reloc_offset(reloc) < reloc_offset(r))
 					r = reloc;
 			}
 		}
@@ -830,11 +831,12 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	}
 
 	reloc->sec = rsec;
-	reloc->offset = offset;
 	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
+	reloc->rel.r_offset = offset;
+
 	if (elf_write_reloc(elf, reloc))
 		return NULL;
 
@@ -908,7 +910,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 		return -1;
 	}
 
-	reloc->offset = reloc->rel.r_offset;
 	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
 	reloc->addend = rela ? reloc->rela.r_addend : 0;
 
@@ -1230,7 +1231,6 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 	struct section *rsec = reloc->sec;
 	int ret;
 
-	reloc->rel.r_offset = reloc->offset;
 	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 
 	if (rsec->sh.sh_type == SHT_RELA) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2a14da6..2070860 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -75,7 +75,6 @@ struct reloc {
 	struct section *sec;
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
-	unsigned long offset;
 	s64 addend;
 	unsigned int type;
 	bool jump_table_start;
@@ -204,6 +203,11 @@ static inline unsigned int reloc_idx(struct reloc *reloc)
 	return reloc - reloc->sec->relocs;
 }
 
+static inline unsigned long reloc_offset(struct reloc *reloc)
+{
+	return reloc->rel.r_offset;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -253,7 +257,7 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
 
 static inline u32 reloc_hash(struct reloc *reloc)
 {
-	return sec_offset_hash(reloc->sec, reloc->offset);
+	return sec_offset_hash(reloc->sec, reloc_offset(reloc));
 }
 
 #endif /* _OBJTOOL_ELF_H */

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->idx
  2023-05-30 17:21 ` [PATCH 13/22] objtool: Get rid of reloc->idx Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     be9a4c116824c39720001db5bc45fe7528b26cff
Gitweb:        https://git.kernel.org/tip/be9a4c116824c39720001db5bc45fe7528b26cff
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:05 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:21 -07:00

objtool: Get rid of reloc->idx

Use the array offset to calculate the reloc index.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 45.56G
- After:  peak heap memory consumption: 43.83G

Link: https://lore.kernel.org/r/7351d2ebad0519027db14a32f6204af84952574a.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 |  6 ++----
 tools/objtool/include/objtool/elf.h | 10 +++++++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 19ac53a..70c8012 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -829,7 +829,6 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 	}
 
-	reloc->idx = reloc_idx;
 	reloc->sec = rsec;
 	reloc->offset = offset;
 	reloc->type = type;
@@ -954,7 +953,6 @@ static int read_relocs(struct elf *elf)
 				return -1;
 
 			reloc->sec = rsec;
-			reloc->idx = i;
 			symndx = GELF_R_SYM(reloc->rel.r_info);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
@@ -1237,9 +1235,9 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 
 	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
-		ret = gelf_update_rela(rsec->data, reloc->idx, &reloc->rela);
+		ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
 	} else {
-		ret = gelf_update_rel(rsec->data, reloc->idx, &reloc->rel);
+		ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
 	}
 
 	if (!ret) {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a09da20..2a14da6 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -76,9 +76,8 @@ struct reloc {
 	struct symbol *sym;
 	struct list_head sym_reloc_entry;
 	unsigned long offset;
-	unsigned int type;
 	s64 addend;
-	int idx;
+	unsigned int type;
 	bool jump_table_start;
 };
 
@@ -200,6 +199,11 @@ static inline unsigned int sec_num_entries(struct section *sec)
 	return sec->sh.sh_size / sec->sh.sh_entsize;
 }
 
+static inline unsigned int reloc_idx(struct reloc *reloc)
+{
+	return reloc - reloc->sec->relocs;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -219,7 +223,7 @@ static inline unsigned int sec_num_entries(struct section *sec)
 		     __i++, reloc++)
 
 #define for_each_reloc_from(rsec, reloc)				\
-	for (int __i = reloc->idx;					\
+	for (int __i = reloc_idx(reloc);				\
 	     __i < sec_num_entries(rsec);				\
 	     __i++, reloc++)
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Allocate relocs in advance for new rela sections
  2023-05-30 17:21 ` [PATCH 11/22] objtool: Allocate relocs in advance for new rela sections Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     e0a9349b4c590145c6a83e6c9f7701cec42debbd
Gitweb:        https://git.kernel.org/tip/e0a9349b4c590145c6a83e6c9f7701cec42debbd
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:03 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:20 -07:00

objtool: Allocate relocs in advance for new rela sections

Similar to read_relocs(), allocate the reloc structs all together in an
array rather than allocating them one at a time.

Link: https://lore.kernel.org/r/5332d845c5a2d6c2d052075b381bfba8bcb67ed5.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8d53f18..5f69d45 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -814,7 +814,7 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 				    unsigned long offset, struct symbol *sym,
 				    s64 addend, unsigned int type)
 {
-	struct reloc *reloc;
+	struct reloc *reloc, empty = { 0 };
 
 	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
 		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
@@ -822,12 +822,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 	}
 
-	reloc = malloc(sizeof(*reloc));
-	if (!reloc) {
-		perror("malloc");
+	reloc = &rsec->reloc_data[reloc_idx];
+
+	if (memcmp(reloc, &empty, sizeof(empty))) {
+		WARN("%s: %s: reloc %d already initialized!",
+		     __func__, rsec->name, reloc_idx);
 		return NULL;
 	}
-	memset(reloc, 0, sizeof(*reloc));
 
 	reloc->idx = reloc_idx;
 	reloc->sec = rsec;
@@ -1185,6 +1186,13 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
+	rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
+				  sizeof(struct reloc));
+	if (!rsec->reloc_data) {
+		perror("calloc");
+		return NULL;
+	}
+
 	sec->rsec = rsec;
 	rsec->base = sec;
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Get rid of reloc->list
  2023-05-30 17:21 ` [PATCH 12/22] objtool: Get rid of reloc->list Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     ebcef730a19ba7ca446169f391d2e51722d68043
Gitweb:        https://git.kernel.org/tip/ebcef730a19ba7ca446169f391d2e51722d68043
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:04 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:20 -07:00

objtool: Get rid of reloc->list

Now that all relocs are allocated in an array, the linked list is no
longer needed.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 49.02G
- After:  peak heap memory consumption: 45.56G

Link: https://lore.kernel.org/r/71e7a2c017dbc46bb497857ec97d67214f832d10.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 32 +++++++++++-----------------
 tools/objtool/include/objtool/elf.h | 18 +++++++++++-----
 2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 5f69d45..19ac53a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -293,7 +293,6 @@ static int read_sections(struct elf *elf)
 		sec = &elf->section_data[i];
 
 		INIT_LIST_HEAD(&sec->symbol_list);
-		INIT_LIST_HEAD(&sec->reloc_list);
 
 		s = elf_getscn(elf->elf, i);
 		if (!s) {
@@ -333,7 +332,7 @@ static int read_sections(struct elf *elf)
 		elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
 
 		if (is_reloc_sec(sec))
-			elf->num_relocs += sec->sh.sh_size / sec->sh.sh_entsize;
+			elf->num_relocs += sec_num_entries(sec);
 	}
 
 	if (opts.stats) {
@@ -407,7 +406,7 @@ static int read_symbols(struct elf *elf)
 		if (symtab_shndx)
 			shndx_data = symtab_shndx->data;
 
-		symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize;
+		symbols_nr = sec_num_entries(symtab);
 	} else {
 		/*
 		 * A missing symbol table is actually possible if it's an empty
@@ -701,7 +700,7 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 		return NULL;
 	}
 
-	new_idx = symtab->sh.sh_size / symtab->sh.sh_entsize;
+	new_idx = sec_num_entries(symtab);
 
 	if (GELF_ST_BIND(sym->sym.st_info) != STB_LOCAL)
 		goto non_local;
@@ -816,13 +815,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 {
 	struct reloc *reloc, empty = { 0 };
 
-	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
-		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
-		     __func__, reloc_idx, rsec->name, rsec->sh.sh_size);
+	if (reloc_idx >= sec_num_entries(rsec)) {
+		WARN("%s: bad reloc_idx %u for %s with %d relocs",
+		     __func__, reloc_idx, rsec->name, sec_num_entries(rsec));
 		return NULL;
 	}
 
-	reloc = &rsec->reloc_data[reloc_idx];
+	reloc = &rsec->relocs[reloc_idx];
 
 	if (memcmp(reloc, &empty, sizeof(empty))) {
 		WARN("%s: %s: reloc %d already initialized!",
@@ -841,7 +840,6 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 		return NULL;
 
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 	return reloc;
@@ -944,14 +942,13 @@ static int read_relocs(struct elf *elf)
 		rsec->base->rsec = rsec;
 
 		nr_reloc = 0;
-		rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
-					  sizeof(*reloc));
-		if (!rsec->reloc_data) {
+		rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc));
+		if (!rsec->relocs) {
 			perror("calloc");
 			return -1;
 		}
-		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
-			reloc = &rsec->reloc_data[i];
+		for (i = 0; i < sec_num_entries(rsec); i++) {
+			reloc = &rsec->relocs[i];
 
 			if (read_reloc(rsec, i, reloc))
 				return -1;
@@ -967,7 +964,6 @@ static int read_relocs(struct elf *elf)
 			}
 
 			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-			list_add_tail(&reloc->list, &rsec->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 			nr_reloc++;
@@ -1093,7 +1089,6 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	memset(sec, 0, sizeof(*sec));
 
 	INIT_LIST_HEAD(&sec->symbol_list);
-	INIT_LIST_HEAD(&sec->reloc_list);
 
 	s = elf_newscn(elf->elf);
 	if (!s) {
@@ -1186,9 +1181,8 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
-				  sizeof(struct reloc));
-	if (!rsec->reloc_data) {
+	rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
+	if (!rsec->relocs) {
 		perror("calloc");
 		return NULL;
 	}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a938cb1..a09da20 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -33,14 +33,13 @@ struct section {
 	GElf_Shdr sh;
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
-	struct list_head reloc_list;
 	struct section *base, *rsec;
 	struct symbol *sym;
 	Elf_Data *data;
 	char *name;
 	int idx;
 	bool _changed, text, rodata, noinstr, init, truncate;
-	struct reloc *reloc_data;
+	struct reloc *relocs;
 };
 
 struct symbol {
@@ -68,7 +67,6 @@ struct symbol {
 };
 
 struct reloc {
-	struct list_head list;
 	struct hlist_node hash;
 	union {
 		GElf_Rela rela;
@@ -197,6 +195,11 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 	elf->changed |= changed;
 }
 
+static inline unsigned int sec_num_entries(struct section *sec)
+{
+	return sec->sh.sh_size / sec->sh.sh_entsize;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -210,10 +213,15 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 			sec_for_each_sym(__sec, sym)
 
 #define for_each_reloc(rsec, reloc)					\
-	list_for_each_entry(reloc, &rsec->reloc_list, list)
+	for (int __i = 0, __fake = 1; __fake; __fake = 0)		\
+		for (reloc = rsec->relocs;				\
+		     __i < sec_num_entries(rsec);			\
+		     __i++, reloc++)
 
 #define for_each_reloc_from(rsec, reloc)				\
-	list_for_each_entry_from(reloc, &rsec->reloc_list, list)
+	for (int __i = reloc->idx;					\
+	     __i < sec_num_entries(rsec);				\
+	     __i++, reloc++)
 
 #define OFFSET_STRIDE_BITS	4
 #define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Add for_each_reloc()
  2023-05-30 17:21 ` [PATCH 10/22] objtool: Add for_each_reloc() Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     caa4a6b74b405ddaea40e2946cc3983aac96451d
Gitweb:        https://git.kernel.org/tip/caa4a6b74b405ddaea40e2946cc3983aac96451d
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:02 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:19 -07:00

objtool: Add for_each_reloc()

Link: https://lore.kernel.org/r/dbfcb1037d8b958e52d097b67829c4c6811c24bb.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 24 ++++++++++++------------
 tools/objtool/include/objtool/elf.h |  6 ++++++
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 3bc97c2..e21138d 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -591,7 +591,7 @@ static int add_dead_ends(struct objtool_file *file)
 	if (!rsec)
 		goto reachable;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -626,7 +626,7 @@ reachable:
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -1019,7 +1019,7 @@ static void add_ignores(struct objtool_file *file)
 	if (!rsec)
 		return;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		switch (reloc->sym->type) {
 		case STT_FUNC:
 			func = reloc->sym;
@@ -1260,7 +1260,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -1991,7 +1991,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 	 * Each @reloc is a switch table relocation which points to the target
 	 * instruction.
 	 */
-	list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {
+	for_each_reloc_from(table->sec, reloc) {
 
 		/* Check for the end of the table: */
 		if (reloc != table && reloc->jump_table_start)
@@ -2270,7 +2270,7 @@ static int read_noendbr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
@@ -2293,7 +2293,7 @@ static int read_retpoline_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2329,7 +2329,7 @@ static int read_instr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2348,7 +2348,7 @@ static int read_instr_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2376,7 +2376,7 @@ static int read_validate_unret_hints(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
@@ -2404,7 +2404,7 @@ static int read_intra_function_calls(struct objtool_file *file)
 	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
+	for_each_reloc(rsec, reloc) {
 		unsigned long dest_off;
 
 		if (reloc->sym->type != STT_SECTION) {
@@ -4404,7 +4404,7 @@ static int validate_ibt(struct objtool_file *file)
 		    strstr(sec->name, "__patchable_function_entries"))
 			continue;
 
-		list_for_each_entry(reloc, &sec->rsec->reloc_list, list)
+		for_each_reloc(sec->rsec, reloc)
 			warnings += validate_ibt_data_reloc(file, reloc);
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 74f6393..a938cb1 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -209,6 +209,12 @@ static inline void mark_sec_changed(struct elf *elf, struct section *sec,
 		for_each_sec(file, __sec)				\
 			sec_for_each_sym(__sec, sym)
 
+#define for_each_reloc(rsec, reloc)					\
+	list_for_each_entry(reloc, &rsec->reloc_list, list)
+
+#define for_each_reloc_from(rsec, reloc)				\
+	list_for_each_entry_from(reloc, &rsec->reloc_list, list)
+
 #define OFFSET_STRIDE_BITS	4
 #define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
 #define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Don't free memory in elf_close()
  2023-05-30 17:21 ` [PATCH 09/22] objtool: Don't free memory in elf_close() Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     5201a9bcb7d3f98ab99c17325b0aa925c2888ca3
Gitweb:        https://git.kernel.org/tip/5201a9bcb7d3f98ab99c17325b0aa925c2888ca3
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:01 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:19 -07:00

objtool: Don't free memory in elf_close()

It's not necessary, objtool's about to exit anyway.

Link: https://lore.kernel.org/r/74bdb3058b8f029db8d5b3b5175f2a200804196d.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 8d491b2..8d53f18 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -1350,30 +1350,14 @@ int elf_write(struct elf *elf)
 
 void elf_close(struct elf *elf)
 {
-	struct section *sec, *tmpsec;
-	struct symbol *sym, *tmpsym;
-	struct reloc *reloc, *tmpreloc;
-
 	if (elf->elf)
 		elf_end(elf->elf);
 
 	if (elf->fd > 0)
 		close(elf->fd);
 
-	list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) {
-		list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
-			list_del(&sym->list);
-			hash_del(&sym->hash);
-		}
-		list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) {
-			list_del(&reloc->list);
-			hash_del(&reloc->hash);
-		}
-		list_del(&sec->list);
-		free(sec->reloc_data);
-	}
-
-	free(elf->symbol_data);
-	free(elf->section_data);
-	free(elf);
+	/*
+	 * NOTE: All remaining allocations are leaked on purpose.  Objtool is
+	 * about to exit anyway.
+	 */
 }

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Keep GElf_Rel[a] structs synced
  2023-05-30 17:21 ` [PATCH 08/22] objtool: Keep GElf_Rel[a] structs synced Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     fcf933552bebdecd72b324738c6635f46b0df569
Gitweb:        https://git.kernel.org/tip/fcf933552bebdecd72b324738c6635f46b0df569
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:21:00 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:18 -07:00

objtool: Keep GElf_Rel[a] structs synced

Keep the GElf_Rela structs synced with their 'struct reloc' counterparts
instead of having to go back and "rebuild" them later.

Link: https://lore.kernel.org/r/156d8a3e528a11e5c8577cf552890ed1f2b9567b.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 55 +++++++++++---------------------------------
 1 file changed, 14 insertions(+), 41 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 5cbc9d5..8d491b2 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -534,16 +534,18 @@ err:
 }
 
 /*
- * Ensure that any reloc section containing references to @sym is marked
- * changed such that it will get re-generated in elf_rebuild_reloc_sections()
- * with the new symbol index.
+ * @sym's idx has changed.  Update the relocs which reference it.
  */
-static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym)
+static int elf_update_sym_relocs(struct elf *elf, struct symbol *sym)
 {
 	struct reloc *reloc;
 
-	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry)
-		mark_sec_changed(elf, reloc->sec, true);
+	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry) {
+		if (elf_write_reloc(elf, reloc))
+			return -1;
+	}
+
+	return 0;
 }
 
 /*
@@ -716,13 +718,14 @@ __elf_create_symbol(struct elf *elf, struct symbol *sym)
 		hlist_del(&old->hash);
 		elf_hash_add(symbol, &old->hash, old->idx);
 
-		elf_dirty_reloc_sym(elf, old);
-
 		if (elf_update_symbol(elf, symtab, symtab_shndx, old)) {
 			WARN("elf_update_symbol move");
 			return NULL;
 		}
 
+		if (elf_update_sym_relocs(elf, old))
+			return NULL;
+
 		new_idx = first_non_local;
 	}
 
@@ -833,12 +836,13 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 	reloc->sym = sym;
 	reloc->addend = addend;
 
+	if (elf_write_reloc(elf, reloc))
+		return NULL;
+
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
 	list_add_tail(&reloc->list, &rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
-	mark_sec_changed(elf, rsec, true);
-
 	return reloc;
 }
 
@@ -1203,31 +1207,6 @@ struct section *elf_create_section_pair(struct elf *elf, const char *name,
 	return sec;
 }
 
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
-{
-	struct reloc *reloc;
-	int idx = 0, ret;
-
-	idx = 0;
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
-		reloc->rel.r_offset = reloc->offset;
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (rsec->sh.sh_type == SHT_RELA) {
-			reloc->rela.r_addend = reloc->addend;
-			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
-		} else {
-			ret = gelf_update_rel(rsec->data, idx, &reloc->rel);
-		}
-		if (!ret) {
-			WARN_ELF("gelf_update_rel");
-			return -1;
-		}
-		idx++;
-	}
-
-	return 0;
-}
-
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn)
@@ -1351,12 +1330,6 @@ int elf_write(struct elf *elf)
 				return -1;
 			}
 
-			if (sec->base &&
-			    elf_rebuild_reloc_section(elf, sec)) {
-				WARN("elf_rebuild_reloc_section");
-				return -1;
-			}
-
 			mark_sec_changed(elf, sec, false);
 		}
 	}

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Add elf_create_section_pair()
  2023-05-30 17:20 ` [PATCH 07/22] objtool: Add elf_create_section_pair() Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     6342a20efbd8b70d169c325b2c27a8a8f96388d5
Gitweb:        https://git.kernel.org/tip/6342a20efbd8b70d169c325b2c27a8a8f96388d5
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:59 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:17 -07:00

objtool: Add elf_create_section_pair()

When creating an annotation section, allocate the reloc section data at
the beginning.  This simplifies the data model a bit and also saves
memory due to the removal of malloc() in elf_rebuild_reloc_section().

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 53.49G
- After:  peak heap memory consumption: 49.02G

Link: https://lore.kernel.org/r/048e908f3ede9b66c15e44672b6dda992b1dae3e.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/arch/powerpc/include/arch/elf.h |  11 +-
 tools/objtool/arch/x86/include/arch/elf.h     |  11 +-
 tools/objtool/check.c                         | 129 +++++----------
 tools/objtool/elf.c                           | 151 ++++++++++-------
 tools/objtool/include/objtool/elf.h           |  33 +++-
 tools/objtool/orc_gen.c                       |   6 +-
 6 files changed, 184 insertions(+), 157 deletions(-)

diff --git a/tools/objtool/arch/powerpc/include/arch/elf.h b/tools/objtool/arch/powerpc/include/arch/elf.h
index 73f9ae1..66814fa 100644
--- a/tools/objtool/arch/powerpc/include/arch/elf.h
+++ b/tools/objtool/arch/powerpc/include/arch/elf.h
@@ -1,10 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
-
 #ifndef _OBJTOOL_ARCH_ELF
 #define _OBJTOOL_ARCH_ELF
 
-#define R_NONE R_PPC_NONE
-#define R_ABS64 R_PPC64_ADDR64
-#define R_ABS32 R_PPC_ADDR32
+#define R_NONE		R_PPC_NONE
+#define R_ABS64		R_PPC64_ADDR64
+#define R_ABS32		R_PPC_ADDR32
+#define R_DATA32	R_PPC_REL32
+#define R_DATA64	R_PPC64_REL64
+#define R_TEXT32	R_PPC_REL32
+#define R_TEXT64	R_PPC64_REL32
 
 #endif /* _OBJTOOL_ARCH_ELF */
diff --git a/tools/objtool/arch/x86/include/arch/elf.h b/tools/objtool/arch/x86/include/arch/elf.h
index ac14987..7131f7f 100644
--- a/tools/objtool/arch/x86/include/arch/elf.h
+++ b/tools/objtool/arch/x86/include/arch/elf.h
@@ -1,8 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 #ifndef _OBJTOOL_ARCH_ELF
 #define _OBJTOOL_ARCH_ELF
 
-#define R_NONE R_X86_64_NONE
-#define R_ABS64 R_X86_64_64
-#define R_ABS32 R_X86_64_32
+#define R_NONE		R_X86_64_NONE
+#define R_ABS32		R_X86_64_32
+#define R_ABS64		R_X86_64_64
+#define R_DATA32	R_X86_64_PC32
+#define R_DATA64	R_X86_64_PC32
+#define R_TEXT32	R_X86_64_PC32
+#define R_TEXT64	R_X86_64_PC32
 
 #endif /* _OBJTOOL_ARCH_ELF */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 2ab8699..3bc97c2 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -8,7 +8,6 @@
 #include <inttypes.h>
 #include <sys/mman.h>
 
-#include <arch/elf.h>
 #include <objtool/builtin.h>
 #include <objtool/cfi.h>
 #include <objtool/arch.h>
@@ -656,8 +655,8 @@ reachable:
 
 static int create_static_call_sections(struct objtool_file *file)
 {
-	struct section *sec;
 	struct static_call_site *site;
+	struct section *sec;
 	struct instruction *insn;
 	struct symbol *key_sym;
 	char *key_name, *tmp;
@@ -677,25 +676,21 @@ static int create_static_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->static_call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".static_call_sites",
-				 sizeof(struct static_call_site), idx);
+	sec = elf_create_section_pair(file->elf, ".static_call_sites",
+				      sizeof(*site), idx, idx * 2);
 	if (!sec)
 		return -1;
 
-	/* Allow modules to set the low bits of static_call_site::key */
+	/* Allow modules to modify the low bits of static_call_site::key */
 	sec->sh.sh_flags |= SHF_WRITE;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->static_call_list, call_node) {
 
-		site = (struct static_call_site *)sec->data->d_buf + idx;
-		memset(site, 0, sizeof(struct static_call_site));
-
 		/* populate reloc for 'addr' */
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(struct static_call_site),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(*site), idx * 2,
+					     insn->sec, insn->offset))
 			return -1;
 
 		/* find key symbol */
@@ -735,10 +730,10 @@ static int create_static_call_sections(struct objtool_file *file)
 		free(key_name);
 
 		/* populate reloc for 'key' */
-		if (elf_add_reloc(file->elf, sec,
-				  idx * sizeof(struct static_call_site) + 4,
-				  R_X86_64_PC32, key_sym,
-				  is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
+		if (!elf_init_reloc_data_sym(file->elf, sec,
+					     idx * sizeof(*site) + 4,
+					     (idx * 2) + 1, key_sym,
+					     is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
 			return -1;
 
 		idx++;
@@ -766,26 +761,18 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".retpoline_sites",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .retpoline_sites");
+	sec = elf_create_section_pair(file->elf, ".retpoline_sites",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
 
-		int *site = (int *)sec->data->d_buf + idx;
-		*site = 0;
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .retpoline_sites");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -812,26 +799,18 @@ static int create_return_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".return_sites",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .return_sites");
+	sec = elf_create_section_pair(file->elf, ".return_sites",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->return_thunk_list, call_node) {
 
-		int *site = (int *)sec->data->d_buf + idx;
-		*site = 0;
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .return_sites");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -864,12 +843,10 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".ibt_endbr_seal",
-				 sizeof(int), idx);
-	if (!sec) {
-		WARN("elf_create_section: .ibt_endbr_seal");
+	sec = elf_create_section_pair(file->elf, ".ibt_endbr_seal",
+				      sizeof(int), idx, idx);
+	if (!sec)
 		return -1;
-	}
 
 	idx = 0;
 	list_for_each_entry(insn, &file->endbr_list, call_node) {
@@ -884,13 +861,10 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 		     !strcmp(sym->name, "cleanup_module")))
 			WARN("%s(): not an indirect call target", sym->name);
 
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset)) {
-			WARN("elf_add_reloc_to_insn: .ibt_endbr_seal");
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(int), idx,
+					     insn->sec, insn->offset))
 			return -1;
-		}
 
 		idx++;
 	}
@@ -902,7 +876,6 @@ static int create_cfi_sections(struct objtool_file *file)
 {
 	struct section *sec;
 	struct symbol *sym;
-	unsigned int *loc;
 	int idx;
 
 	sec = find_section_by_name(file->elf, ".cfi_sites");
@@ -923,7 +896,8 @@ static int create_cfi_sections(struct objtool_file *file)
 		idx++;
 	}
 
-	sec = elf_create_section(file->elf, ".cfi_sites", sizeof(unsigned int), idx);
+	sec = elf_create_section_pair(file->elf, ".cfi_sites",
+				      sizeof(unsigned int), idx, idx);
 	if (!sec)
 		return -1;
 
@@ -935,13 +909,9 @@ static int create_cfi_sections(struct objtool_file *file)
 		if (strncmp(sym->name, "__cfi_", 6))
 			continue;
 
-		loc = (unsigned int *)sec->data->d_buf + idx;
-		memset(loc, 0, sizeof(unsigned int));
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(unsigned int),
-					  R_X86_64_PC32,
-					  sym->sec, sym->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(unsigned int), idx,
+					     sym->sec, sym->offset))
 			return -1;
 
 		idx++;
@@ -971,7 +941,8 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", addr_size, idx);
+	sec = elf_create_section_pair(file->elf, "__mcount_loc", addr_size,
+				      idx, idx);
 	if (!sec)
 		return -1;
 
@@ -979,17 +950,17 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 
 	idx = 0;
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
-		void *loc;
 
-		loc = sec->data->d_buf + idx;
-		memset(loc, 0, addr_size);
+		struct reloc *reloc;
 
-		if (elf_add_reloc_to_insn(file->elf, sec, idx,
-					  addr_size == sizeof(u64) ? R_ABS64 : R_ABS32,
-					  insn->sec, insn->offset))
+		reloc = elf_init_reloc_text_sym(file->elf, sec, idx * addr_size, idx,
+					       insn->sec, insn->offset);
+		if (!reloc)
 			return -1;
 
-		idx += addr_size;
+		reloc->type = addr_size == 8 ? R_ABS64 : R_ABS32;
+
+		idx++;
 	}
 
 	return 0;
@@ -999,7 +970,6 @@ static int create_direct_call_sections(struct objtool_file *file)
 {
 	struct instruction *insn;
 	struct section *sec;
-	unsigned int *loc;
 	int idx;
 
 	sec = find_section_by_name(file->elf, ".call_sites");
@@ -1016,20 +986,17 @@ static int create_direct_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".call_sites", sizeof(unsigned int), idx);
+	sec = elf_create_section_pair(file->elf, ".call_sites",
+				      sizeof(unsigned int), idx, idx);
 	if (!sec)
 		return -1;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->call_list, call_node) {
 
-		loc = (unsigned int *)sec->data->d_buf + idx;
-		memset(loc, 0, sizeof(unsigned int));
-
-		if (elf_add_reloc_to_insn(file->elf, sec,
-					  idx * sizeof(unsigned int),
-					  R_X86_64_PC32,
-					  insn->sec, insn->offset))
+		if (!elf_init_reloc_text_sym(file->elf, sec,
+					     idx * sizeof(unsigned int), idx,
+					     insn->sec, insn->offset))
 			return -1;
 
 		idx++;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 67967c2..5cbc9d5 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -533,41 +533,6 @@ err:
 	return -1;
 }
 
-static struct section *elf_create_rela_section(struct elf *elf,
-					       struct section *sec);
-
-int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
-		  unsigned int type, struct symbol *sym, s64 addend)
-{
-	struct reloc *reloc;
-
-	if (!sec->rsec && !elf_create_rela_section(elf, sec))
-		return -1;
-
-	reloc = malloc(sizeof(*reloc));
-	if (!reloc) {
-		perror("malloc");
-		return -1;
-	}
-	memset(reloc, 0, sizeof(*reloc));
-
-	reloc->sec = sec->rsec;
-	reloc->offset = offset;
-	reloc->type = type;
-	reloc->sym = sym;
-	reloc->addend = addend;
-
-	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &sec->rsec->reloc_list);
-	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
-
-	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
-
-	mark_sec_changed(elf, sec->rsec, true);
-
-	return 0;
-}
-
 /*
  * Ensure that any reloc section containing references to @sym is marked
  * changed such that it will get re-generated in elf_rebuild_reloc_sections()
@@ -841,13 +806,57 @@ elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size)
 	return sym;
 }
 
-int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
-			  unsigned long offset, unsigned int type,
-			  struct section *insn_sec, unsigned long insn_off)
+static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
+				    unsigned int reloc_idx,
+				    unsigned long offset, struct symbol *sym,
+				    s64 addend, unsigned int type)
+{
+	struct reloc *reloc;
+
+	if (reloc_idx >= rsec->sh.sh_size / elf_rela_size(elf)) {
+		WARN("%s: bad reloc_idx %u for %s with size 0x%lx",
+		     __func__, reloc_idx, rsec->name, rsec->sh.sh_size);
+		return NULL;
+	}
+
+	reloc = malloc(sizeof(*reloc));
+	if (!reloc) {
+		perror("malloc");
+		return NULL;
+	}
+	memset(reloc, 0, sizeof(*reloc));
+
+	reloc->idx = reloc_idx;
+	reloc->sec = rsec;
+	reloc->offset = offset;
+	reloc->type = type;
+	reloc->sym = sym;
+	reloc->addend = addend;
+
+	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
+	list_add_tail(&reloc->list, &rsec->reloc_list);
+	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
+
+	mark_sec_changed(elf, rsec, true);
+
+	return reloc;
+}
+
+struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct section *insn_sec,
+				      unsigned long insn_off)
 {
 	struct symbol *sym = insn_sec->sym;
 	int addend = insn_off;
 
+	if (!(insn_sec->sh.sh_flags & SHF_EXECINSTR)) {
+		WARN("bad call to %s() for data symbol %s",
+		     __func__, sym->name);
+		return NULL;
+	}
+
 	if (!sym) {
 		/*
 		 * Due to how weak functions work, we must use section based
@@ -857,12 +866,29 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 		 */
 		sym = elf_create_section_symbol(elf, insn_sec);
 		if (!sym)
-			return -1;
+			return NULL;
 
 		insn_sec->sym = sym;
 	}
 
-	return elf_add_reloc(elf, sec, offset, type, sym, addend);
+	return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend,
+			      elf_text_rela_type(elf));
+}
+
+struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct symbol *sym,
+				      s64 addend)
+{
+	if (sym->sec && (sec->sh.sh_flags & SHF_EXECINSTR)) {
+		WARN("bad call to %s() for text symbol %s",
+		     __func__, sym->name);
+		return NULL;
+	}
+
+	return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend,
+			      elf_data_rela_type(elf));
 }
 
 static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
@@ -1048,7 +1074,7 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 }
 
 struct section *elf_create_section(struct elf *elf, const char *name,
-				   size_t entsize, int nr)
+				   size_t entsize, unsigned int nr)
 {
 	struct section *sec, *shstrtab;
 	size_t size = entsize * nr;
@@ -1129,7 +1155,8 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 }
 
 static struct section *elf_create_rela_section(struct elf *elf,
-					       struct section *sec)
+					       struct section *sec,
+					       unsigned int reloc_nr)
 {
 	struct section *rsec;
 	char *rsec_name;
@@ -1142,46 +1169,50 @@ static struct section *elf_create_rela_section(struct elf *elf,
 	strcpy(rsec_name, ".rela");
 	strcat(rsec_name, sec->name);
 
-	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), 0);
+	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), reloc_nr);
 	free(rsec_name);
 	if (!rsec)
 		return NULL;
 
-	sec->rsec = rsec;
-	rsec->base = sec;
-
+	rsec->data->d_type = ELF_T_RELA;
 	rsec->sh.sh_type = SHT_RELA;
 	rsec->sh.sh_addralign = elf_addr_size(elf);
 	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
 	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
+	sec->rsec = rsec;
+	rsec->base = sec;
+
 	return rsec;
 }
 
+struct section *elf_create_section_pair(struct elf *elf, const char *name,
+					size_t entsize, unsigned int nr,
+					unsigned int reloc_nr)
+{
+	struct section *sec;
+
+	sec = elf_create_section(elf, name, entsize, nr);
+	if (!sec)
+		return NULL;
+
+	if (!elf_create_rela_section(elf, sec, reloc_nr))
+		return NULL;
+
+	return sec;
+}
+
 static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
-	bool rela = rsec->sh.sh_type == SHT_RELA;
 	struct reloc *reloc;
 	int idx = 0, ret;
-	void *buf;
-
-	/* Allocate a buffer for relocations */
-	buf = malloc(rsec->sh.sh_size);
-	if (!buf) {
-		perror("malloc");
-		return -1;
-	}
-
-	rsec->data->d_buf = buf;
-	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = rela ? ELF_T_RELA : ELF_T_REL;
 
 	idx = 0;
 	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (rela) {
+		if (rsec->sh.sh_type == SHT_RELA) {
 			reloc->rela.r_addend = reloc->addend;
 			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
 		} else {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 56b66ff..74f6393 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -111,15 +111,26 @@ struct elf {
 };
 
 struct elf *elf_open_read(const char *name, int flags);
-struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
+
+struct section *elf_create_section(struct elf *elf, const char *name,
+				   size_t entsize, unsigned int nr);
+struct section *elf_create_section_pair(struct elf *elf, const char *name,
+					size_t entsize, unsigned int nr,
+					unsigned int reloc_nr);
 
 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
 
-int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
-		  unsigned int type, struct symbol *sym, s64 addend);
-int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
-			  unsigned long offset, unsigned int type,
-			  struct section *insn_sec, unsigned long insn_off);
+struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct section *insn_sec,
+				      unsigned long insn_off);
+
+struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
+				      unsigned long offset,
+				      unsigned int reloc_idx,
+				      struct symbol *sym,
+				      s64 addend);
 
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
@@ -159,6 +170,16 @@ static inline size_t elf_rela_size(struct elf *elf)
 	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
+static inline unsigned int elf_data_rela_type(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? R_DATA32 : R_DATA64;
+}
+
+static inline unsigned int elf_text_rela_type(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64;
+}
+
 static inline bool is_reloc_sec(struct section *sec)
 {
 	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index d5f750b..bae3439 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -118,8 +118,8 @@ static int write_orc_entry(struct elf *elf, struct section *orc_sec,
 	orc->bp_offset = bswap_if_needed(elf, orc->bp_offset);
 
 	/* populate reloc for ip */
-	if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32,
-				  insn_sec, insn_off))
+	if (!elf_init_reloc_text_sym(elf, ip_sec, idx * sizeof(int), idx,
+				     insn_sec, insn_off))
 		return -1;
 
 	return 0;
@@ -242,7 +242,7 @@ int orc_create(struct objtool_file *file)
 	if (!orc_sec)
 		return -1;
 
-	sec = elf_create_section(file->elf, ".orc_unwind_ip", sizeof(int), nr);
+	sec = elf_create_section_pair(file->elf, ".orc_unwind_ip", sizeof(int), nr, nr);
 	if (!sec)
 		return -1;
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Add mark_sec_changed()
  2023-05-30 17:20 ` [PATCH 06/22] objtool: Add mark_sec_changed() Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     ff4082730c2aaff3706232266e09d1ae4b350521
Gitweb:        https://git.kernel.org/tip/ff4082730c2aaff3706232266e09d1ae4b350521
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:58 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:16 -07:00

objtool: Add mark_sec_changed()

Ensure elf->changed always gets set when sec->changed gets set.

Link: https://lore.kernel.org/r/9a810a8d2e28af6ba07325362d0eb4703bb09d3a.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 31 ++++++++++++++--------------
 tools/objtool/include/objtool/elf.h | 14 ++++++++++++-
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index f72ec6d..67967c2 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -562,7 +562,8 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
-	sec->rsec->changed = true;
+
+	mark_sec_changed(elf, sec->rsec, true);
 
 	return 0;
 }
@@ -577,7 +578,7 @@ static void elf_dirty_reloc_sym(struct elf *elf, struct symbol *sym)
 	struct reloc *reloc;
 
 	list_for_each_entry(reloc, &sym->reloc_list, sym_reloc_entry)
-		reloc->sec->changed = true;
+		mark_sec_changed(elf, reloc->sec, true);
 }
 
 /*
@@ -654,7 +655,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
 			symtab_data->d_align = 1;
 			symtab_data->d_type = ELF_T_SYM;
 
-			symtab->changed = true;
+			mark_sec_changed(elf, symtab, true);
 			symtab->truncate = true;
 
 			if (t) {
@@ -669,7 +670,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
 				shndx_data->d_align = sizeof(Elf32_Word);
 				shndx_data->d_type = ELF_T_WORD;
 
-				symtab_shndx->changed = true;
+				mark_sec_changed(elf, symtab_shndx, true);
 				symtab_shndx->truncate = true;
 			}
 
@@ -773,11 +774,11 @@ non_local:
 	}
 
 	symtab->sh.sh_size += symtab->sh.sh_entsize;
-	symtab->changed = true;
+	mark_sec_changed(elf, symtab, true);
 
 	if (symtab_shndx) {
 		symtab_shndx->sh.sh_size += sizeof(Elf32_Word);
-		symtab_shndx->changed = true;
+		mark_sec_changed(elf, symtab_shndx, true);
 	}
 
 	return sym;
@@ -1040,7 +1041,8 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 
 	len = strtab->sh.sh_size;
 	strtab->sh.sh_size += data->d_size;
-	strtab->changed = true;
+
+	mark_sec_changed(elf, strtab, true);
 
 	return len;
 }
@@ -1075,7 +1077,6 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	}
 
 	sec->idx = elf_ndxscn(s);
-	sec->changed = true;
 
 	sec->data = elf_newdata(s);
 	if (!sec->data) {
@@ -1122,7 +1123,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	elf_hash_add(section, &sec->hash, sec->idx);
 	elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
 
-	elf->changed = true;
+	mark_sec_changed(elf, sec, true);
 
 	return sec;
 }
@@ -1208,9 +1209,8 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 	}
 
 	memcpy(data->d_buf + offset, insn, len);
-	elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
 
-	elf->changed = true;
+	mark_sec_changed(elf, sec, true);
 
 	return 0;
 }
@@ -1235,7 +1235,7 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 		return -1;
 	}
 
-	elf->changed = true;
+	mark_sec_changed(elf, rsec, true);
 
 	return 0;
 }
@@ -1307,12 +1307,14 @@ int elf_write(struct elf *elf)
 		if (sec->truncate)
 			elf_truncate_section(elf, sec);
 
-		if (sec->changed) {
+		if (sec_changed(sec)) {
 			s = elf_getscn(elf->elf, sec->idx);
 			if (!s) {
 				WARN_ELF("elf_getscn");
 				return -1;
 			}
+
+			/* Note this also flags the section dirty */
 			if (!gelf_update_shdr(s, &sec->sh)) {
 				WARN_ELF("gelf_update_shdr");
 				return -1;
@@ -1324,8 +1326,7 @@ int elf_write(struct elf *elf)
 				return -1;
 			}
 
-			sec->changed = false;
-			elf->changed = true;
+			mark_sec_changed(elf, sec, false);
 		}
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index b81d78b..56b66ff 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -39,7 +39,7 @@ struct section {
 	Elf_Data *data;
 	char *name;
 	int idx;
-	bool changed, text, rodata, noinstr, init, truncate;
+	bool _changed, text, rodata, noinstr, init, truncate;
 	struct reloc *reloc_data;
 };
 
@@ -164,6 +164,18 @@ static inline bool is_reloc_sec(struct section *sec)
 	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
 }
 
+static inline bool sec_changed(struct section *sec)
+{
+	return sec->_changed;
+}
+
+static inline void mark_sec_changed(struct elf *elf, struct section *sec,
+				    bool changed)
+{
+	sec->_changed = changed;
+	elf->changed |= changed;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Fix reloc_hash size
  2023-05-30 17:20 ` [PATCH 05/22] objtool: Fix reloc_hash size Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     eb0481bbc4ce386e73e28ad8590b4f12c8aded56
Gitweb:        https://git.kernel.org/tip/eb0481bbc4ce386e73e28ad8590b4f12c8aded56
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:57 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:16 -07:00

objtool: Fix reloc_hash size

With CONFIG_DEBUG_INFO, DWARF creates a lot of relocations and
reloc_hash is woefully undersized, which can affect performance
significantly.  Fix that.

Link: https://lore.kernel.org/r/38ef60dc8043270bf3b9dfd139ae2a30ca3f75cc.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c                 | 16 +++++++---------
 tools/objtool/include/objtool/elf.h |  8 +++++++-
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 4bbdd8e..f72ec6d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -328,12 +328,12 @@ static int read_sections(struct elf *elf)
 			}
 		}
 
-		if (sec->sh.sh_flags & SHF_EXECINSTR)
-			elf->text_size += sec->sh.sh_size;
-
 		list_add_tail(&sec->list, &elf->sections);
 		elf_hash_add(section, &sec->hash, sec->idx);
 		elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
+
+		if (is_reloc_sec(sec))
+			elf->num_relocs += sec->sh.sh_size / sec->sh.sh_entsize;
 	}
 
 	if (opts.stats) {
@@ -888,19 +888,18 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 
 static int read_relocs(struct elf *elf)
 {
-	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
+	unsigned long nr_reloc, max_reloc = 0;
 	struct section *rsec;
 	struct reloc *reloc;
 	unsigned int symndx;
 	struct symbol *sym;
 	int i;
 
-	if (!elf_alloc_hash(reloc, elf->text_size / 16))
+	if (!elf_alloc_hash(reloc, elf->num_relocs))
 		return -1;
 
 	list_for_each_entry(rsec, &elf->sections, list) {
-		if ((rsec->sh.sh_type != SHT_RELA) &&
-		    (rsec->sh.sh_type != SHT_REL))
+		if (!is_reloc_sec(rsec))
 			continue;
 
 		rsec->base = find_section_by_index(elf, rsec->sh.sh_info);
@@ -942,12 +941,11 @@ static int read_relocs(struct elf *elf)
 			nr_reloc++;
 		}
 		max_reloc = max(max_reloc, nr_reloc);
-		tot_reloc += nr_reloc;
 	}
 
 	if (opts.stats) {
 		printf("max_reloc: %lu\n", max_reloc);
-		printf("tot_reloc: %lu\n", tot_reloc);
+		printf("num_relocs: %lu\n", elf->num_relocs);
 		printf("reloc_bits: %d\n", elf->reloc_bits);
 	}
 
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 6f82f25..b81d78b 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -90,8 +90,9 @@ struct elf {
 	int fd;
 	bool changed;
 	char *name;
-	unsigned int text_size, num_files;
+	unsigned int num_files;
 	struct list_head sections;
+	unsigned long num_relocs;
 
 	int symbol_bits;
 	int symbol_name_bits;
@@ -158,6 +159,11 @@ static inline size_t elf_rela_size(struct elf *elf)
 	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
+static inline bool is_reloc_sec(struct section *sec)
+{
+	return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL;
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Consolidate rel/rela handling
  2023-05-30 17:20 ` [PATCH 04/22] objtool: Consolidate rel/rela handling Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     53257a977a69b5eabbaafb64dcd767d2a4fef2b3
Gitweb:        https://git.kernel.org/tip/53257a977a69b5eabbaafb64dcd767d2a4fef2b3
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:56 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:15 -07:00

objtool: Consolidate rel/rela handling

The GElf_Rel[a] structs have more similarities than differences.  It's
safe to hard-code the assumptions about their shared fields as they will
never change.  Consolidate their handling where possible, getting rid of
duplicated code.

Also, at least for now we only ever create rela sections, so simplify
the relocation creation code to be rela-only.

Link: https://lore.kernel.org/r/dcabf6df400ca500ea929f1e4284f5e5ec0b27c8.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               |  12 +-
 tools/objtool/elf.c                 | 202 +++++++--------------------
 tools/objtool/include/objtool/elf.h |  13 +-
 3 files changed, 68 insertions(+), 159 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f4c52a2..2ab8699 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -952,7 +952,7 @@ static int create_cfi_sections(struct objtool_file *file)
 
 static int create_mcount_loc_sections(struct objtool_file *file)
 {
-	int addrsize = elf_class_addrsize(file->elf);
+	size_t addr_size = elf_addr_size(file->elf);
 	struct instruction *insn;
 	struct section *sec;
 	int idx;
@@ -971,25 +971,25 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", addrsize, idx);
+	sec = elf_create_section(file->elf, "__mcount_loc", addr_size, idx);
 	if (!sec)
 		return -1;
 
-	sec->sh.sh_addralign = addrsize;
+	sec->sh.sh_addralign = addr_size;
 
 	idx = 0;
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node) {
 		void *loc;
 
 		loc = sec->data->d_buf + idx;
-		memset(loc, 0, addrsize);
+		memset(loc, 0, addr_size);
 
 		if (elf_add_reloc_to_insn(file->elf, sec, idx,
-					  addrsize == sizeof(u64) ? R_ABS64 : R_ABS32,
+					  addr_size == sizeof(u64) ? R_ABS64 : R_ABS32,
 					  insn->sec, insn->offset))
 			return -1;
 
-		idx += addrsize;
+		idx += addr_size;
 	}
 
 	return 0;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 86ae62d..4bbdd8e 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -533,16 +533,15 @@ err:
 	return -1;
 }
 
-static struct section *elf_create_reloc_section(struct elf *elf,
-						struct section *sec,
-						int reltype);
+static struct section *elf_create_rela_section(struct elf *elf,
+					       struct section *sec);
 
 int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 		  unsigned int type, struct symbol *sym, s64 addend)
 {
 	struct reloc *reloc;
 
-	if (!sec->rsec && !elf_create_reloc_section(elf, sec, SHT_RELA))
+	if (!sec->rsec && !elf_create_rela_section(elf, sec))
 		return -1;
 
 	reloc = malloc(sizeof(*reloc));
@@ -865,29 +864,25 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 	return elf_add_reloc(elf, sec, offset, type, sym, addend);
 }
 
-static int read_rel_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
 {
-	if (!gelf_getrel(rsec->data, i, &reloc->rel)) {
-		WARN_ELF("gelf_getrel");
-		return -1;
-	}
-	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
-	reloc->addend = 0;
-	reloc->offset = reloc->rel.r_offset;
-	*symndx = GELF_R_SYM(reloc->rel.r_info);
-	return 0;
-}
+	bool rela = rsec->sh.sh_type == SHT_RELA;
+	void *retp;
 
-static int read_rela_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
-{
-	if (!gelf_getrela(rsec->data, i, &reloc->rela)) {
+	if (rela)
+		retp = gelf_getrela(rsec->data, i, &reloc->rela);
+	else
+		retp = gelf_getrel(rsec->data, i, &reloc->rel);
+
+	if (!retp) {
 		WARN_ELF("gelf_getrela");
 		return -1;
 	}
-	reloc->type = GELF_R_TYPE(reloc->rela.r_info);
-	reloc->addend = reloc->rela.r_addend;
-	reloc->offset = reloc->rela.r_offset;
-	*symndx = GELF_R_SYM(reloc->rela.r_info);
+
+	reloc->offset = reloc->rel.r_offset;
+	reloc->type = GELF_R_TYPE(reloc->rel.r_info);
+	reloc->addend = rela ? reloc->rela.r_addend : 0;
+
 	return 0;
 }
 
@@ -926,20 +921,13 @@ static int read_relocs(struct elf *elf)
 		}
 		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
 			reloc = &rsec->reloc_data[i];
-			switch (rsec->sh.sh_type) {
-			case SHT_REL:
-				if (read_rel_reloc(rsec, i, reloc, &symndx))
-					return -1;
-				break;
-			case SHT_RELA:
-				if (read_rela_reloc(rsec, i, reloc, &symndx))
-					return -1;
-				break;
-			default: return -1;
-			}
+
+			if (read_reloc(rsec, i, reloc))
+				return -1;
 
 			reloc->sec = rsec;
 			reloc->idx = i;
+			symndx = GELF_R_SYM(reloc->rel.r_info);
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
@@ -1141,86 +1129,42 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	return sec;
 }
 
-static struct section *elf_create_rel_reloc_section(struct elf *elf,
-						    struct section *sec)
+static struct section *elf_create_rela_section(struct elf *elf,
+					       struct section *sec)
 {
-	char *relocname;
 	struct section *rsec;
+	char *rsec_name;
 
-	relocname = malloc(strlen(sec->name) + strlen(".rel") + 1);
-	if (!relocname) {
+	rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1);
+	if (!rsec_name) {
 		perror("malloc");
 		return NULL;
 	}
-	strcpy(relocname, ".rel");
-	strcat(relocname, sec->name);
+	strcpy(rsec_name, ".rela");
+	strcat(rsec_name, sec->name);
 
-	rsec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
-	free(relocname);
+	rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), 0);
+	free(rsec_name);
 	if (!rsec)
 		return NULL;
 
 	sec->rsec = rsec;
 	rsec->base = sec;
 
-	rsec->sh.sh_type = SHT_REL;
-	rsec->sh.sh_addralign = 8;
-	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	rsec->sh.sh_info = sec->idx;
-	rsec->sh.sh_flags = SHF_INFO_LINK;
-
-	return rsec;
-}
-
-static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base)
-{
-	char *relocname;
-	struct section *rsec;
-	int addrsize = elf_class_addrsize(elf);
-
-	relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
-	if (!relocname) {
-		perror("malloc");
-		return NULL;
-	}
-	strcpy(relocname, ".rela");
-	strcat(relocname, base->name);
-
-	if (addrsize == sizeof(u32))
-		rsec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
-	else
-		rsec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
-	free(relocname);
-	if (!rsec)
-		return NULL;
-
-	base->rsec = rsec;
-	rsec->base = base;
-
 	rsec->sh.sh_type = SHT_RELA;
-	rsec->sh.sh_addralign = addrsize;
+	rsec->sh.sh_addralign = elf_addr_size(elf);
 	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	rsec->sh.sh_info = base->idx;
+	rsec->sh.sh_info = sec->idx;
 	rsec->sh.sh_flags = SHF_INFO_LINK;
 
 	return rsec;
 }
 
-static struct section *elf_create_reloc_section(struct elf *elf,
-					 struct section *base,
-					 int reltype)
-{
-	switch (reltype) {
-	case SHT_REL:  return elf_create_rel_reloc_section(elf, base);
-	case SHT_RELA: return elf_create_rela_reloc_section(elf, base);
-	default:       return NULL;
-	}
-}
-
-static int elf_rebuild_rel_reloc_section(struct section *rsec)
+static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
+	bool rela = rsec->sh.sh_type == SHT_RELA;
 	struct reloc *reloc;
-	int idx = 0;
+	int idx = 0, ret;
 	void *buf;
 
 	/* Allocate a buffer for relocations */
@@ -1232,46 +1176,20 @@ static int elf_rebuild_rel_reloc_section(struct section *rsec)
 
 	rsec->data->d_buf = buf;
 	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = ELF_T_REL;
+	rsec->data->d_type = rela ? ELF_T_RELA : ELF_T_REL;
 
 	idx = 0;
 	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rel(rsec->data, idx, &reloc->rel)) {
-			WARN_ELF("gelf_update_rel");
-			return -1;
+		if (rela) {
+			reloc->rela.r_addend = reloc->addend;
+			ret = gelf_update_rela(rsec->data, idx, &reloc->rela);
+		} else {
+			ret = gelf_update_rel(rsec->data, idx, &reloc->rel);
 		}
-		idx++;
-	}
-
-	return 0;
-}
-
-static int elf_rebuild_rela_reloc_section(struct section *rsec)
-{
-	struct reloc *reloc;
-	int idx = 0;
-	void *buf;
-
-	/* Allocate a buffer for relocations with addends */
-	buf = malloc(rsec->sh.sh_size);
-	if (!buf) {
-		perror("malloc");
-		return -1;
-	}
-
-	rsec->data->d_buf = buf;
-	rsec->data->d_size = rsec->sh.sh_size;
-	rsec->data->d_type = ELF_T_RELA;
-
-	idx = 0;
-	list_for_each_entry(reloc, &rsec->reloc_list, list) {
-		reloc->rela.r_offset = reloc->offset;
-		reloc->rela.r_addend = reloc->addend;
-		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rela(rsec->data, idx, &reloc->rela)) {
-			WARN_ELF("gelf_update_rela");
+		if (!ret) {
+			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
 		idx++;
@@ -1280,15 +1198,6 @@ static int elf_rebuild_rela_reloc_section(struct section *rsec)
 	return 0;
 }
 
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
-{
-	switch (rsec->sh.sh_type) {
-	case SHT_REL:  return elf_rebuild_rel_reloc_section(rsec);
-	case SHT_RELA: return elf_rebuild_rela_reloc_section(rsec);
-	default:       return -1;
-	}
-}
-
 int elf_write_insn(struct elf *elf, struct section *sec,
 		   unsigned long offset, unsigned int len,
 		   const char *insn)
@@ -1311,24 +1220,21 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 {
 	struct section *rsec = reloc->sec;
+	int ret;
 
-	if (rsec->sh.sh_type == SHT_REL) {
-		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		reloc->rel.r_offset = reloc->offset;
+	reloc->rel.r_offset = reloc->offset;
+	reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 
-		if (!gelf_update_rel(rsec->data, reloc->idx, &reloc->rel)) {
-			WARN_ELF("gelf_update_rel");
-			return -1;
-		}
-	} else {
-		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
+	if (rsec->sh.sh_type == SHT_RELA) {
 		reloc->rela.r_addend = reloc->addend;
-		reloc->rela.r_offset = reloc->offset;
+		ret = gelf_update_rela(rsec->data, reloc->idx, &reloc->rela);
+	} else {
+		ret = gelf_update_rel(rsec->data, reloc->idx, &reloc->rel);
+	}
 
-		if (!gelf_update_rela(rsec->data, reloc->idx, &reloc->rela)) {
-			WARN_ELF("gelf_update_rela");
-			return -1;
-		}
+	if (!ret) {
+		WARN_ELF("gelf_update_rela");
+		return -1;
 	}
 
 	elf->changed = true;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index a4e43a6..6f82f25 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -12,6 +12,7 @@
 #include <linux/hashtable.h>
 #include <linux/rbtree.h>
 #include <linux/jhash.h>
+#include <arch/elf.h>
 
 #ifdef LIBELF_USE_DEPRECATED
 # define elf_getshdrnum    elf_getshnum
@@ -147,12 +148,14 @@ static inline bool has_multiple_files(struct elf *elf)
 	return elf->num_files > 1;
 }
 
-static inline int elf_class_addrsize(struct elf *elf)
+static inline size_t elf_addr_size(struct elf *elf)
 {
-	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
-		return sizeof(u32);
-	else
-		return sizeof(u64);
+	return elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+}
+
+static inline size_t elf_rela_size(struct elf *elf)
+{
+	return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela);
 }
 
 #define for_each_sec(file, sec)						\

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Improve reloc naming
  2023-05-30 17:20 ` [PATCH 03/22] objtool: Improve reloc naming Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     a5bd623653231bce8657978e9d2c2ebfaf19e297
Gitweb:        https://git.kernel.org/tip/a5bd623653231bce8657978e9d2c2ebfaf19e297
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:55 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:14 -07:00

objtool: Improve reloc naming

- The term "reloc" is overloaded to mean both "an instance of struct
  reloc" and "a reloc section".  Change the latter to "rsec".

- For variable names, use "sec" for regular sections and "rsec" for rela
  sections to prevent them getting mixed up.

- For struct reloc variables, use "reloc" instead of "rel" everywhere
  for consistency.

Link: https://lore.kernel.org/r/8b790e403df46f445c21003e7893b8f53b99a6f3.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 134 +++++++++++-----------
 tools/objtool/elf.c                 | 164 +++++++++++++--------------
 tools/objtool/include/objtool/elf.h |   2 +-
 3 files changed, 151 insertions(+), 149 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index eaf6815..f4c52a2 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -494,7 +494,7 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 {
 	struct symbol *sym, *func;
 	unsigned long off, end;
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
 	sym = find_symbol_by_name(file->elf, symname);
@@ -504,19 +504,19 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 	off = sym->offset;
 	end = off + sym->len;
 	for (;;) {
-		rel = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
-		if (!rel)
+		reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
+		if (!reloc)
 			break;
 
-		func = rel->sym;
+		func = reloc->sym;
 		if (func->type == STT_SECTION)
-			func = find_symbol_by_offset(rel->sym->sec, rel->addend);
+			func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
 
-		idx = (rel->offset - sym->offset) / sizeof(unsigned long);
+		idx = (reloc->offset - sym->offset) / sizeof(unsigned long);
 
 		objtool_pv_add(file, idx, func);
 
-		off = rel->offset + 1;
+		off = reloc->offset + 1;
 		if (off > end)
 			break;
 	}
@@ -581,20 +581,20 @@ static struct instruction *find_last_insn(struct objtool_file *file,
  */
 static int add_dead_ends(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
 
 	/*
 	 * Check for manually annotated dead ends.
 	 */
-	sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.unreachable");
+	if (!rsec)
 		goto reachable;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
@@ -623,13 +623,13 @@ reachable:
 	 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
 	 * not a dead end.
 	 */
-	sec = find_section_by_name(file->elf, ".rela.discard.reachable");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.reachable");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 		insn = find_insn(file, reloc->sym->sec, reloc->addend);
@@ -1044,15 +1044,15 @@ static int create_direct_call_sections(struct objtool_file *file)
 static void add_ignores(struct objtool_file *file)
 {
 	struct instruction *insn;
-	struct section *sec;
+	struct section *rsec;
 	struct symbol *func;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
+	if (!rsec)
 		return;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		switch (reloc->sym->type) {
 		case STT_FUNC:
 			func = reloc->sym;
@@ -1065,7 +1065,8 @@ static void add_ignores(struct objtool_file *file)
 			break;
 
 		default:
-			WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
+			WARN("unexpected relocation symbol type in %s: %d",
+			     rsec->name, reloc->sym->type);
 			continue;
 		}
 
@@ -1284,17 +1285,17 @@ static void add_uaccess_safe(struct objtool_file *file)
  */
 static int add_ignore_alternatives(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	struct instruction *insn;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2204,7 +2205,7 @@ static void set_func_state(struct cfi_state *state)
 static int read_unwind_hints(struct objtool_file *file)
 {
 	struct cfi_state cfi = init_cfi;
-	struct section *sec, *relocsec;
+	struct section *sec;
 	struct unwind_hint *hint;
 	struct instruction *insn;
 	struct reloc *reloc;
@@ -2214,8 +2215,7 @@ static int read_unwind_hints(struct objtool_file *file)
 	if (!sec)
 		return 0;
 
-	relocsec = sec->reloc;
-	if (!relocsec) {
+	if (!sec->rsec) {
 		WARN("missing .rela.discard.unwind_hints section");
 		return -1;
 	}
@@ -2295,15 +2295,15 @@ static int read_unwind_hints(struct objtool_file *file)
 
 static int read_noendbr_hints(struct objtool_file *file)
 {
-	struct section *sec;
 	struct instruction *insn;
+	struct section *rsec;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.noendbr");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.noendbr");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
 		if (!insn) {
 			WARN("bad .discard.noendbr entry");
@@ -2318,17 +2318,17 @@ static int read_noendbr_hints(struct objtool_file *file)
 
 static int read_retpoline_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2354,17 +2354,17 @@ static int read_retpoline_hints(struct objtool_file *file)
 
 static int read_instr_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.instr_end");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2377,13 +2377,13 @@ static int read_instr_hints(struct objtool_file *file)
 		insn->instr--;
 	}
 
-	sec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.instr_begin");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2401,17 +2401,17 @@ static int read_instr_hints(struct objtool_file *file)
 
 static int read_validate_unret_hints(struct objtool_file *file)
 {
-	struct section *sec;
+	struct section *rsec;
 	struct instruction *insn;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.validate_unret");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		if (reloc->sym->type != STT_SECTION) {
-			WARN("unexpected relocation symbol type in %s", sec->name);
+			WARN("unexpected relocation symbol type in %s", rsec->name);
 			return -1;
 		}
 
@@ -2430,19 +2430,19 @@ static int read_validate_unret_hints(struct objtool_file *file)
 static int read_intra_function_calls(struct objtool_file *file)
 {
 	struct instruction *insn;
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 
-	sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
-	if (!sec)
+	rsec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
+	if (!rsec)
 		return 0;
 
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		unsigned long dest_off;
 
 		if (reloc->sym->type != STT_SECTION) {
 			WARN("unexpected relocation symbol type in %s",
-			     sec->name);
+			     rsec->name);
 			return -1;
 		}
 
@@ -3342,15 +3342,15 @@ static inline bool func_uaccess_safe(struct symbol *func)
 static inline const char *call_dest_name(struct instruction *insn)
 {
 	static char pvname[19];
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
 	if (insn_call_dest(insn))
 		return insn_call_dest(insn)->name;
 
-	rel = insn_reloc(NULL, insn);
-	if (rel && !strcmp(rel->sym->name, "pv_ops")) {
-		idx = (rel->addend / sizeof(void *));
+	reloc = insn_reloc(NULL, insn);
+	if (reloc && !strcmp(reloc->sym->name, "pv_ops")) {
+		idx = (reloc->addend / sizeof(void *));
 		snprintf(pvname, sizeof(pvname), "pv_ops[%d]", idx);
 		return pvname;
 	}
@@ -3361,14 +3361,14 @@ static inline const char *call_dest_name(struct instruction *insn)
 static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
 {
 	struct symbol *target;
-	struct reloc *rel;
+	struct reloc *reloc;
 	int idx;
 
-	rel = insn_reloc(file, insn);
-	if (!rel || strcmp(rel->sym->name, "pv_ops"))
+	reloc = insn_reloc(file, insn);
+	if (!reloc || strcmp(reloc->sym->name, "pv_ops"))
 		return false;
 
-	idx = (arch_dest_reloc_offset(rel->addend) / sizeof(void *));
+	idx = (arch_dest_reloc_offset(reloc->addend) / sizeof(void *));
 
 	if (file->pv_ops[idx].clean)
 		return true;
@@ -4410,7 +4410,7 @@ static int validate_ibt(struct objtool_file *file)
 		if (sec->sh.sh_flags & SHF_EXECINSTR)
 			continue;
 
-		if (!sec->reloc)
+		if (!sec->rsec)
 			continue;
 
 		/*
@@ -4437,7 +4437,7 @@ static int validate_ibt(struct objtool_file *file)
 		    strstr(sec->name, "__patchable_function_entries"))
 			continue;
 
-		list_for_each_entry(reloc, &sec->reloc->reloc_list, list)
+		list_for_each_entry(reloc, &sec->rsec->reloc_list, list)
 			warnings += validate_ibt_data_reloc(file, reloc);
 	}
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 7598c0a..86ae62d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -233,17 +233,17 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 				     unsigned long offset, unsigned int len)
 {
 	struct reloc *reloc, *r = NULL;
+	struct section *rsec;
 	unsigned long o;
 
-	if (!sec->reloc)
+	rsec = sec->rsec;
+	if (!rsec)
 		return NULL;
 
-	sec = sec->reloc;
-
 	for_offset_range(o, offset, offset + len) {
 		elf_hash_for_each_possible(reloc, reloc, hash,
-					   sec_offset_hash(sec, o)) {
-			if (reloc->sec != sec)
+					   sec_offset_hash(rsec, o)) {
+			if (reloc->sec != rsec)
 				continue;
 
 			if (reloc->offset >= offset && reloc->offset < offset + len) {
@@ -534,7 +534,7 @@ err:
 }
 
 static struct section *elf_create_reloc_section(struct elf *elf,
-						struct section *base,
+						struct section *sec,
 						int reltype);
 
 int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
@@ -542,7 +542,7 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 {
 	struct reloc *reloc;
 
-	if (!sec->reloc && !elf_create_reloc_section(elf, sec, SHT_RELA))
+	if (!sec->rsec && !elf_create_reloc_section(elf, sec, SHT_RELA))
 		return -1;
 
 	reloc = malloc(sizeof(*reloc));
@@ -552,18 +552,18 @@ int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
 	}
 	memset(reloc, 0, sizeof(*reloc));
 
-	reloc->sec = sec->reloc;
+	reloc->sec = sec->rsec;
 	reloc->offset = offset;
 	reloc->type = type;
 	reloc->sym = sym;
 	reloc->addend = addend;
 
 	list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-	list_add_tail(&reloc->list, &sec->reloc->reloc_list);
+	list_add_tail(&reloc->list, &sec->rsec->reloc_list);
 	elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
-	sec->reloc->sh.sh_size += sec->reloc->sh.sh_entsize;
-	sec->reloc->changed = true;
+	sec->rsec->sh.sh_size += sec->rsec->sh.sh_entsize;
+	sec->rsec->changed = true;
 
 	return 0;
 }
@@ -865,9 +865,9 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
 	return elf_add_reloc(elf, sec, offset, type, sym, addend);
 }
 
-static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_rel_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
 {
-	if (!gelf_getrel(sec->data, i, &reloc->rel)) {
+	if (!gelf_getrel(rsec->data, i, &reloc->rel)) {
 		WARN_ELF("gelf_getrel");
 		return -1;
 	}
@@ -878,9 +878,9 @@ static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsig
 	return 0;
 }
 
-static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
+static int read_rela_reloc(struct section *rsec, int i, struct reloc *reloc, unsigned int *symndx)
 {
-	if (!gelf_getrela(sec->data, i, &reloc->rela)) {
+	if (!gelf_getrela(rsec->data, i, &reloc->rela)) {
 		WARN_ELF("gelf_getrela");
 		return -1;
 	}
@@ -894,7 +894,7 @@ static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsi
 static int read_relocs(struct elf *elf)
 {
 	unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
-	struct section *sec;
+	struct section *rsec;
 	struct reloc *reloc;
 	unsigned int symndx;
 	struct symbol *sym;
@@ -903,51 +903,52 @@ static int read_relocs(struct elf *elf)
 	if (!elf_alloc_hash(reloc, elf->text_size / 16))
 		return -1;
 
-	list_for_each_entry(sec, &elf->sections, list) {
-		if ((sec->sh.sh_type != SHT_RELA) &&
-		    (sec->sh.sh_type != SHT_REL))
+	list_for_each_entry(rsec, &elf->sections, list) {
+		if ((rsec->sh.sh_type != SHT_RELA) &&
+		    (rsec->sh.sh_type != SHT_REL))
 			continue;
 
-		sec->base = find_section_by_index(elf, sec->sh.sh_info);
-		if (!sec->base) {
+		rsec->base = find_section_by_index(elf, rsec->sh.sh_info);
+		if (!rsec->base) {
 			WARN("can't find base section for reloc section %s",
-			     sec->name);
+			     rsec->name);
 			return -1;
 		}
 
-		sec->base->reloc = sec;
+		rsec->base->rsec = rsec;
 
 		nr_reloc = 0;
-		sec->reloc_data = calloc(sec->sh.sh_size / sec->sh.sh_entsize, sizeof(*reloc));
-		if (!sec->reloc_data) {
+		rsec->reloc_data = calloc(rsec->sh.sh_size / rsec->sh.sh_entsize,
+					  sizeof(*reloc));
+		if (!rsec->reloc_data) {
 			perror("calloc");
 			return -1;
 		}
-		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
-			reloc = &sec->reloc_data[i];
-			switch (sec->sh.sh_type) {
+		for (i = 0; i < rsec->sh.sh_size / rsec->sh.sh_entsize; i++) {
+			reloc = &rsec->reloc_data[i];
+			switch (rsec->sh.sh_type) {
 			case SHT_REL:
-				if (read_rel_reloc(sec, i, reloc, &symndx))
+				if (read_rel_reloc(rsec, i, reloc, &symndx))
 					return -1;
 				break;
 			case SHT_RELA:
-				if (read_rela_reloc(sec, i, reloc, &symndx))
+				if (read_rela_reloc(rsec, i, reloc, &symndx))
 					return -1;
 				break;
 			default: return -1;
 			}
 
-			reloc->sec = sec;
+			reloc->sec = rsec;
 			reloc->idx = i;
 			reloc->sym = sym = find_symbol_by_index(elf, symndx);
 			if (!reloc->sym) {
 				WARN("can't find reloc entry symbol %d for %s",
-				     symndx, sec->name);
+				     symndx, rsec->name);
 				return -1;
 			}
 
 			list_add_tail(&reloc->sym_reloc_entry, &sym->reloc_list);
-			list_add_tail(&reloc->list, &sec->reloc_list);
+			list_add_tail(&reloc->list, &rsec->reloc_list);
 			elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc));
 
 			nr_reloc++;
@@ -1140,40 +1141,41 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	return sec;
 }
 
-static struct section *elf_create_rel_reloc_section(struct elf *elf, struct section *base)
+static struct section *elf_create_rel_reloc_section(struct elf *elf,
+						    struct section *sec)
 {
 	char *relocname;
-	struct section *sec;
+	struct section *rsec;
 
-	relocname = malloc(strlen(base->name) + strlen(".rel") + 1);
+	relocname = malloc(strlen(sec->name) + strlen(".rel") + 1);
 	if (!relocname) {
 		perror("malloc");
 		return NULL;
 	}
 	strcpy(relocname, ".rel");
-	strcat(relocname, base->name);
+	strcat(relocname, sec->name);
 
-	sec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
+	rsec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
 	free(relocname);
-	if (!sec)
+	if (!rsec)
 		return NULL;
 
-	base->reloc = sec;
-	sec->base = base;
+	sec->rsec = rsec;
+	rsec->base = sec;
 
-	sec->sh.sh_type = SHT_REL;
-	sec->sh.sh_addralign = 8;
-	sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	sec->sh.sh_info = base->idx;
-	sec->sh.sh_flags = SHF_INFO_LINK;
+	rsec->sh.sh_type = SHT_REL;
+	rsec->sh.sh_addralign = 8;
+	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
+	rsec->sh.sh_info = sec->idx;
+	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	return sec;
+	return rsec;
 }
 
 static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base)
 {
 	char *relocname;
-	struct section *sec;
+	struct section *rsec;
 	int addrsize = elf_class_addrsize(elf);
 
 	relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
@@ -1185,23 +1187,23 @@ static struct section *elf_create_rela_reloc_section(struct elf *elf, struct sec
 	strcat(relocname, base->name);
 
 	if (addrsize == sizeof(u32))
-		sec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
+		rsec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
 	else
-		sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
+		rsec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
 	free(relocname);
-	if (!sec)
+	if (!rsec)
 		return NULL;
 
-	base->reloc = sec;
-	sec->base = base;
+	base->rsec = rsec;
+	rsec->base = base;
 
-	sec->sh.sh_type = SHT_RELA;
-	sec->sh.sh_addralign = addrsize;
-	sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
-	sec->sh.sh_info = base->idx;
-	sec->sh.sh_flags = SHF_INFO_LINK;
+	rsec->sh.sh_type = SHT_RELA;
+	rsec->sh.sh_addralign = addrsize;
+	rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
+	rsec->sh.sh_info = base->idx;
+	rsec->sh.sh_flags = SHF_INFO_LINK;
 
-	return sec;
+	return rsec;
 }
 
 static struct section *elf_create_reloc_section(struct elf *elf,
@@ -1215,28 +1217,28 @@ static struct section *elf_create_reloc_section(struct elf *elf,
 	}
 }
 
-static int elf_rebuild_rel_reloc_section(struct section *sec)
+static int elf_rebuild_rel_reloc_section(struct section *rsec)
 {
 	struct reloc *reloc;
 	int idx = 0;
 	void *buf;
 
 	/* Allocate a buffer for relocations */
-	buf = malloc(sec->sh.sh_size);
+	buf = malloc(rsec->sh.sh_size);
 	if (!buf) {
 		perror("malloc");
 		return -1;
 	}
 
-	sec->data->d_buf = buf;
-	sec->data->d_size = sec->sh.sh_size;
-	sec->data->d_type = ELF_T_REL;
+	rsec->data->d_buf = buf;
+	rsec->data->d_size = rsec->sh.sh_size;
+	rsec->data->d_type = ELF_T_REL;
 
 	idx = 0;
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rel.r_offset = reloc->offset;
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rel(sec->data, idx, &reloc->rel)) {
+		if (!gelf_update_rel(rsec->data, idx, &reloc->rel)) {
 			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
@@ -1246,29 +1248,29 @@ static int elf_rebuild_rel_reloc_section(struct section *sec)
 	return 0;
 }
 
-static int elf_rebuild_rela_reloc_section(struct section *sec)
+static int elf_rebuild_rela_reloc_section(struct section *rsec)
 {
 	struct reloc *reloc;
 	int idx = 0;
 	void *buf;
 
 	/* Allocate a buffer for relocations with addends */
-	buf = malloc(sec->sh.sh_size);
+	buf = malloc(rsec->sh.sh_size);
 	if (!buf) {
 		perror("malloc");
 		return -1;
 	}
 
-	sec->data->d_buf = buf;
-	sec->data->d_size = sec->sh.sh_size;
-	sec->data->d_type = ELF_T_RELA;
+	rsec->data->d_buf = buf;
+	rsec->data->d_size = rsec->sh.sh_size;
+	rsec->data->d_type = ELF_T_RELA;
 
 	idx = 0;
-	list_for_each_entry(reloc, &sec->reloc_list, list) {
+	list_for_each_entry(reloc, &rsec->reloc_list, list) {
 		reloc->rela.r_offset = reloc->offset;
 		reloc->rela.r_addend = reloc->addend;
 		reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
-		if (!gelf_update_rela(sec->data, idx, &reloc->rela)) {
+		if (!gelf_update_rela(rsec->data, idx, &reloc->rela)) {
 			WARN_ELF("gelf_update_rela");
 			return -1;
 		}
@@ -1278,11 +1280,11 @@ static int elf_rebuild_rela_reloc_section(struct section *sec)
 	return 0;
 }
 
-static int elf_rebuild_reloc_section(struct elf *elf, struct section *sec)
+static int elf_rebuild_reloc_section(struct elf *elf, struct section *rsec)
 {
-	switch (sec->sh.sh_type) {
-	case SHT_REL:  return elf_rebuild_rel_reloc_section(sec);
-	case SHT_RELA: return elf_rebuild_rela_reloc_section(sec);
+	switch (rsec->sh.sh_type) {
+	case SHT_REL:  return elf_rebuild_rel_reloc_section(rsec);
+	case SHT_RELA: return elf_rebuild_rela_reloc_section(rsec);
 	default:       return -1;
 	}
 }
@@ -1308,13 +1310,13 @@ int elf_write_insn(struct elf *elf, struct section *sec,
 
 int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 {
-	struct section *sec = reloc->sec;
+	struct section *rsec = reloc->sec;
 
-	if (sec->sh.sh_type == SHT_REL) {
+	if (rsec->sh.sh_type == SHT_REL) {
 		reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
 		reloc->rel.r_offset = reloc->offset;
 
-		if (!gelf_update_rel(sec->data, reloc->idx, &reloc->rel)) {
+		if (!gelf_update_rel(rsec->data, reloc->idx, &reloc->rel)) {
 			WARN_ELF("gelf_update_rel");
 			return -1;
 		}
@@ -1323,7 +1325,7 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
 		reloc->rela.r_addend = reloc->addend;
 		reloc->rela.r_offset = reloc->offset;
 
-		if (!gelf_update_rela(sec->data, reloc->idx, &reloc->rela)) {
+		if (!gelf_update_rela(rsec->data, reloc->idx, &reloc->rela)) {
 			WARN_ELF("gelf_update_rela");
 			return -1;
 		}
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 2c28aee..a4e43a6 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -33,7 +33,7 @@ struct section {
 	struct rb_root_cached symbol_tree;
 	struct list_head symbol_list;
 	struct list_head reloc_list;
-	struct section *base, *reloc;
+	struct section *base, *rsec;
 	struct symbol *sym;
 	Elf_Data *data;
 	char *name;

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Remove flags argument from elf_create_section()
  2023-05-30 17:20 ` [PATCH 02/22] objtool: Remove flags argument from elf_create_section() Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     2707579dfa615a5dda4aabb92e433f03a87b5ec5
Gitweb:        https://git.kernel.org/tip/2707579dfa615a5dda4aabb92e433f03a87b5ec5
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:54 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:13 -07:00

objtool: Remove flags argument from elf_create_section()

Simplify the elf_create_section() interface a bit by removing the flags
argument.  Most callers don't care about changing the section header
flags.  If needed, they can be modified afterwards, just like any other
section header field.

Link: https://lore.kernel.org/r/515235d9cf62637a14bee37bfa9169ef20065471.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c               | 17 ++++++++++-------
 tools/objtool/elf.c                 | 10 +++++-----
 tools/objtool/include/objtool/elf.h |  2 +-
 tools/objtool/orc_gen.c             |  4 ++--
 4 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index b11c25a..eaf6815 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -677,11 +677,14 @@ static int create_static_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->static_call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE,
+	sec = elf_create_section(file->elf, ".static_call_sites",
 				 sizeof(struct static_call_site), idx);
 	if (!sec)
 		return -1;
 
+	/* Allow modules to set the low bits of static_call_site::key */
+	sec->sh.sh_flags |= SHF_WRITE;
+
 	idx = 0;
 	list_for_each_entry(insn, &file->static_call_list, call_node) {
 
@@ -763,7 +766,7 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".retpoline_sites", 0,
+	sec = elf_create_section(file->elf, ".retpoline_sites",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .retpoline_sites");
@@ -809,7 +812,7 @@ static int create_return_sites_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".return_sites", 0,
+	sec = elf_create_section(file->elf, ".return_sites",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .return_sites");
@@ -861,7 +864,7 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
 	if (!idx)
 		return 0;
 
-	sec = elf_create_section(file->elf, ".ibt_endbr_seal", 0,
+	sec = elf_create_section(file->elf, ".ibt_endbr_seal",
 				 sizeof(int), idx);
 	if (!sec) {
 		WARN("elf_create_section: .ibt_endbr_seal");
@@ -920,7 +923,7 @@ static int create_cfi_sections(struct objtool_file *file)
 		idx++;
 	}
 
-	sec = elf_create_section(file->elf, ".cfi_sites", 0, sizeof(unsigned int), idx);
+	sec = elf_create_section(file->elf, ".cfi_sites", sizeof(unsigned int), idx);
 	if (!sec)
 		return -1;
 
@@ -968,7 +971,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->mcount_loc_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, "__mcount_loc", 0, addrsize, idx);
+	sec = elf_create_section(file->elf, "__mcount_loc", addrsize, idx);
 	if (!sec)
 		return -1;
 
@@ -1013,7 +1016,7 @@ static int create_direct_call_sections(struct objtool_file *file)
 	list_for_each_entry(insn, &file->call_list, call_node)
 		idx++;
 
-	sec = elf_create_section(file->elf, ".call_sites", 0, sizeof(unsigned int), idx);
+	sec = elf_create_section(file->elf, ".call_sites", sizeof(unsigned int), idx);
 	if (!sec)
 		return -1;
 
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 500e929..7598c0a 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -1059,7 +1059,7 @@ static int elf_add_string(struct elf *elf, struct section *strtab, char *str)
 }
 
 struct section *elf_create_section(struct elf *elf, const char *name,
-				   unsigned int sh_flags, size_t entsize, int nr)
+				   size_t entsize, int nr)
 {
 	struct section *sec, *shstrtab;
 	size_t size = entsize * nr;
@@ -1117,7 +1117,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
 	sec->sh.sh_entsize = entsize;
 	sec->sh.sh_type = SHT_PROGBITS;
 	sec->sh.sh_addralign = 1;
-	sec->sh.sh_flags = SHF_ALLOC | sh_flags;
+	sec->sh.sh_flags = SHF_ALLOC;
 
 	/* Add section name to .shstrtab (or .strtab for Clang) */
 	shstrtab = find_section_by_name(elf, ".shstrtab");
@@ -1153,7 +1153,7 @@ static struct section *elf_create_rel_reloc_section(struct elf *elf, struct sect
 	strcpy(relocname, ".rel");
 	strcat(relocname, base->name);
 
-	sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rel), 0);
+	sec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
 	free(relocname);
 	if (!sec)
 		return NULL;
@@ -1185,9 +1185,9 @@ static struct section *elf_create_rela_reloc_section(struct elf *elf, struct sec
 	strcat(relocname, base->name);
 
 	if (addrsize == sizeof(u32))
-		sec = elf_create_section(elf, relocname, 0, sizeof(Elf32_Rela), 0);
+		sec = elf_create_section(elf, relocname, sizeof(Elf32_Rela), 0);
 	else
-		sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rela), 0);
+		sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
 	free(relocname);
 	if (!sec)
 		return NULL;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index b24f83e..2c28aee 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -109,7 +109,7 @@ struct elf {
 };
 
 struct elf *elf_open_read(const char *name, int flags);
-struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
+struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
 
 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
 
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index 48efd1e..d5f750b 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -237,12 +237,12 @@ int orc_create(struct objtool_file *file)
 		WARN("file already has .orc_unwind section, skipping");
 		return -1;
 	}
-	orc_sec = elf_create_section(file->elf, ".orc_unwind", 0,
+	orc_sec = elf_create_section(file->elf, ".orc_unwind",
 				     sizeof(struct orc_entry), nr);
 	if (!orc_sec)
 		return -1;
 
-	sec = elf_create_section(file->elf, ".orc_unwind_ip", 0, sizeof(int), nr);
+	sec = elf_create_section(file->elf, ".orc_unwind_ip", sizeof(int), nr);
 	if (!sec)
 		return -1;
 

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [tip: objtool/core] objtool: Tidy elf.h
  2023-05-30 17:20 ` [PATCH 01/22] objtool: Tidy elf.h Josh Poimboeuf
@ 2023-06-09  7:47   ` tip-bot2 for Josh Poimboeuf
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot2 for Josh Poimboeuf @ 2023-06-09  7:47 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Josh Poimboeuf, x86, linux-kernel

The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     809373e17b2649948cc681dd1962b2736b22c7a6
Gitweb:        https://git.kernel.org/tip/809373e17b2649948cc681dd1962b2736b22c7a6
Author:        Josh Poimboeuf <jpoimboe@kernel.org>
AuthorDate:    Tue, 30 May 2023 10:20:53 -07:00
Committer:     Josh Poimboeuf <jpoimboe@kernel.org>
CommitterDate: Wed, 07 Jun 2023 10:03:13 -07:00

objtool: Tidy elf.h

Reorganize elf.h a bit:

- Move the prototypes higher up so they can be used by the inline
  functions.

- Move hash-related code to the bottom.

- Remove the unused ELF_HASH_BITS macro.

No functional changes.

Link: https://lore.kernel.org/r/b1490ed85951868219a6ece177a7cd30a6454d66.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/include/objtool/elf.h | 96 +++++++++++++---------------
 1 file changed, 47 insertions(+), 49 deletions(-)

diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 78e2d0f..b24f83e 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -83,8 +83,6 @@ struct reloc {
 	bool jump_table_start;
 };
 
-#define ELF_HASH_BITS	20
-
 struct elf {
 	Elf *elf;
 	GElf_Ehdr ehdr;
@@ -110,53 +108,6 @@ struct elf {
 	struct symbol *symbol_data;
 };
 
-#define OFFSET_STRIDE_BITS	4
-#define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
-#define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))
-
-#define for_offset_range(_offset, _start, _end)			\
-	for (_offset = ((_start) & OFFSET_STRIDE_MASK);		\
-	     _offset >= ((_start) & OFFSET_STRIDE_MASK) &&	\
-	     _offset <= ((_end) & OFFSET_STRIDE_MASK);		\
-	     _offset += OFFSET_STRIDE)
-
-static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
-{
-	u32 ol, oh, idx = sec->idx;
-
-	offset &= OFFSET_STRIDE_MASK;
-
-	ol = offset;
-	oh = (offset >> 16) >> 16;
-
-	__jhash_mix(ol, oh, idx);
-
-	return ol;
-}
-
-static inline u32 reloc_hash(struct reloc *reloc)
-{
-	return sec_offset_hash(reloc->sec, reloc->offset);
-}
-
-/*
- * Try to see if it's a whole archive (vmlinux.o or module).
- *
- * Note this will miss the case where a module only has one source file.
- */
-static inline bool has_multiple_files(struct elf *elf)
-{
-	return elf->num_files > 1;
-}
-
-static inline int elf_class_addrsize(struct elf *elf)
-{
-	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
-		return sizeof(u32);
-	else
-		return sizeof(u64);
-}
-
 struct elf *elf_open_read(const char *name, int flags);
 struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
 
@@ -186,6 +137,24 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
 				     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
 
+/*
+ * Try to see if it's a whole archive (vmlinux.o or module).
+ *
+ * Note this will miss the case where a module only has one source file.
+ */
+static inline bool has_multiple_files(struct elf *elf)
+{
+	return elf->num_files > 1;
+}
+
+static inline int elf_class_addrsize(struct elf *elf)
+{
+	if (elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+		return sizeof(u32);
+	else
+		return sizeof(u64);
+}
+
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
 
@@ -198,4 +167,33 @@ struct symbol *find_func_containing(struct section *sec, unsigned long offset);
 		for_each_sec(file, __sec)				\
 			sec_for_each_sym(__sec, sym)
 
+#define OFFSET_STRIDE_BITS	4
+#define OFFSET_STRIDE		(1UL << OFFSET_STRIDE_BITS)
+#define OFFSET_STRIDE_MASK	(~(OFFSET_STRIDE - 1))
+
+#define for_offset_range(_offset, _start, _end)			\
+	for (_offset = ((_start) & OFFSET_STRIDE_MASK);		\
+	     _offset >= ((_start) & OFFSET_STRIDE_MASK) &&	\
+	     _offset <= ((_end) & OFFSET_STRIDE_MASK);		\
+	     _offset += OFFSET_STRIDE)
+
+static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
+{
+	u32 ol, oh, idx = sec->idx;
+
+	offset &= OFFSET_STRIDE_MASK;
+
+	ol = offset;
+	oh = (offset >> 16) >> 16;
+
+	__jhash_mix(ol, oh, idx);
+
+	return ol;
+}
+
+static inline u32 reloc_hash(struct reloc *reloc)
+{
+	return sec_offset_hash(reloc->sec, reloc->offset);
+}
+
 #endif /* _OBJTOOL_ELF_H */

^ permalink raw reply related	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2023-06-09  7:50 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-30 17:20 [PATCH 00/22] objtool: Reduce memory usage with CONFIG_DEBUG_INFO Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 01/22] objtool: Tidy elf.h Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 02/22] objtool: Remove flags argument from elf_create_section() Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 03/22] objtool: Improve reloc naming Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 04/22] objtool: Consolidate rel/rela handling Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 05/22] objtool: Fix reloc_hash size Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 06/22] objtool: Add mark_sec_changed() Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:20 ` [PATCH 07/22] objtool: Add elf_create_section_pair() Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 08/22] objtool: Keep GElf_Rel[a] structs synced Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 09/22] objtool: Don't free memory in elf_close() Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 10/22] objtool: Add for_each_reloc() Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 11/22] objtool: Allocate relocs in advance for new rela sections Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 12/22] objtool: Get rid of reloc->list Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 13/22] objtool: Get rid of reloc->idx Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 14/22] objtool: Get rid of reloc->offset Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 15/22] objtool: Get rid of reloc->type Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 16/22] objtool: Get rid of reloc->addend Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 17/22] objtool: Get rid of reloc->jump_table_start Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 18/22] objtool: Shrink reloc->sym_reloc_entry Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 19/22] objtool: Shrink elf hash nodes Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 20/22] objtool: Get rid of reloc->rel[a] Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 21/22] objtool: Free insns when done Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf
2023-05-30 17:21 ` [PATCH 22/22] objtool: Skip reading DWARF section data Josh Poimboeuf
2023-06-09  7:47   ` [tip: objtool/core] " tip-bot2 for Josh Poimboeuf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.