From 8045b8f0b17edf375849f83c80dd05194850b6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Tue, 27 Dec 2022 16:00:59 +0000 Subject: [PATCH] objtool: Allocate multiple structures with calloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using calloc() instead of malloc() in a loop, libc does not have to keep around bookkeeping information for each single structure. This reduces maximum memory usage while processing vmlinux.o from 3153325 KB to 3035668 KB (-3.7%) on my notebooks "localmodconfig". Note this introduces memory leaks, because some additional structs get added to the lists later after reading the symbols and sections from the original object. Luckily we don't really care about memory leaks in objtool. Signed-off-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20221216-objtool-memory-v2-3-17968f85a464@weissschuh.net Signed-off-by: Josh Poimboeuf --- tools/objtool/elf.c | 42 ++++++++++++++--------------- tools/objtool/include/objtool/elf.h | 4 +++ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index 64443a7f4bbf..6806ce01d933 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -284,13 +284,13 @@ static int read_sections(struct elf *elf) !elf_alloc_hash(section_name, sections_nr)) return -1; + elf->section_data = calloc(sections_nr, sizeof(*sec)); + if (!elf->section_data) { + perror("calloc"); + return -1; + } for (i = 0; i < sections_nr; i++) { - sec = malloc(sizeof(*sec)); - if (!sec) { - perror("malloc"); - return -1; - } - memset(sec, 0, sizeof(*sec)); + sec = &elf->section_data[i]; INIT_LIST_HEAD(&sec->symbol_list); INIT_LIST_HEAD(&sec->reloc_list); @@ -422,13 +422,13 @@ static int read_symbols(struct elf *elf) !elf_alloc_hash(symbol_name, symbols_nr)) return -1; + elf->symbol_data = calloc(symbols_nr, sizeof(*sym)); + if (!elf->symbol_data) { + perror("calloc"); + return -1; + } for (i = 0; i < symbols_nr; i++) { - sym = malloc(sizeof(*sym)); - if (!sym) { - perror("malloc"); - return -1; - } - memset(sym, 0, sizeof(*sym)); + sym = &elf->symbol_data[i]; sym->idx = i; @@ -918,13 +918,13 @@ static int read_relocs(struct elf *elf) sec->base->reloc = sec; nr_reloc = 0; + sec->reloc_data = calloc(sec->sh.sh_size / sec->sh.sh_entsize, sizeof(*reloc)); + if (!sec->reloc_data) { + perror("calloc"); + return -1; + } for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { - reloc = malloc(sizeof(*reloc)); - if (!reloc) { - perror("malloc"); - return -1; - } - memset(reloc, 0, sizeof(*reloc)); + reloc = &sec->reloc_data[i]; switch (sec->sh.sh_type) { case SHT_REL: if (read_rel_reloc(sec, i, reloc, &symndx)) @@ -1453,16 +1453,16 @@ void elf_close(struct elf *elf) list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) { list_del(&sym->list); hash_del(&sym->hash); - free(sym); } list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) { list_del(&reloc->list); hash_del(&reloc->hash); - free(reloc); } list_del(&sec->list); - free(sec); + free(sec->reloc_data); } + free(elf->symbol_data); + free(elf->section_data); free(elf); } diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h index bb60fd42b46f..1c90f0ac0d53 100644 --- a/tools/objtool/include/objtool/elf.h +++ b/tools/objtool/include/objtool/elf.h @@ -39,6 +39,7 @@ struct section { char *name; int idx; bool changed, text, rodata, noinstr, init, truncate; + struct reloc *reloc_data; }; struct symbol { @@ -104,6 +105,9 @@ struct elf { struct hlist_head *section_hash; struct hlist_head *section_name_hash; struct hlist_head *reloc_hash; + + struct section *section_data; + struct symbol *symbol_data; }; #define OFFSET_STRIDE_BITS 4