Skip to content

Commit 8045b8f

Browse files
t-8chjpoimboe
authored andcommitted
objtool: Allocate multiple structures with calloc()
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 <linux@weissschuh.net> Link: https://lore.kernel.org/r/20221216-objtool-memory-v2-3-17968f85a464@weissschuh.net Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
1 parent cfd66e8 commit 8045b8f

2 files changed

Lines changed: 25 additions & 21 deletions

File tree

tools/objtool/elf.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,13 @@ static int read_sections(struct elf *elf)
284284
!elf_alloc_hash(section_name, sections_nr))
285285
return -1;
286286

287+
elf->section_data = calloc(sections_nr, sizeof(*sec));
288+
if (!elf->section_data) {
289+
perror("calloc");
290+
return -1;
291+
}
287292
for (i = 0; i < sections_nr; i++) {
288-
sec = malloc(sizeof(*sec));
289-
if (!sec) {
290-
perror("malloc");
291-
return -1;
292-
}
293-
memset(sec, 0, sizeof(*sec));
293+
sec = &elf->section_data[i];
294294

295295
INIT_LIST_HEAD(&sec->symbol_list);
296296
INIT_LIST_HEAD(&sec->reloc_list);
@@ -422,13 +422,13 @@ static int read_symbols(struct elf *elf)
422422
!elf_alloc_hash(symbol_name, symbols_nr))
423423
return -1;
424424

425+
elf->symbol_data = calloc(symbols_nr, sizeof(*sym));
426+
if (!elf->symbol_data) {
427+
perror("calloc");
428+
return -1;
429+
}
425430
for (i = 0; i < symbols_nr; i++) {
426-
sym = malloc(sizeof(*sym));
427-
if (!sym) {
428-
perror("malloc");
429-
return -1;
430-
}
431-
memset(sym, 0, sizeof(*sym));
431+
sym = &elf->symbol_data[i];
432432

433433
sym->idx = i;
434434

@@ -918,13 +918,13 @@ static int read_relocs(struct elf *elf)
918918
sec->base->reloc = sec;
919919

920920
nr_reloc = 0;
921+
sec->reloc_data = calloc(sec->sh.sh_size / sec->sh.sh_entsize, sizeof(*reloc));
922+
if (!sec->reloc_data) {
923+
perror("calloc");
924+
return -1;
925+
}
921926
for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
922-
reloc = malloc(sizeof(*reloc));
923-
if (!reloc) {
924-
perror("malloc");
925-
return -1;
926-
}
927-
memset(reloc, 0, sizeof(*reloc));
927+
reloc = &sec->reloc_data[i];
928928
switch (sec->sh.sh_type) {
929929
case SHT_REL:
930930
if (read_rel_reloc(sec, i, reloc, &symndx))
@@ -1453,16 +1453,16 @@ void elf_close(struct elf *elf)
14531453
list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
14541454
list_del(&sym->list);
14551455
hash_del(&sym->hash);
1456-
free(sym);
14571456
}
14581457
list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) {
14591458
list_del(&reloc->list);
14601459
hash_del(&reloc->hash);
1461-
free(reloc);
14621460
}
14631461
list_del(&sec->list);
1464-
free(sec);
1462+
free(sec->reloc_data);
14651463
}
14661464

1465+
free(elf->symbol_data);
1466+
free(elf->section_data);
14671467
free(elf);
14681468
}

tools/objtool/include/objtool/elf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct section {
3939
char *name;
4040
int idx;
4141
bool changed, text, rodata, noinstr, init, truncate;
42+
struct reloc *reloc_data;
4243
};
4344

4445
struct symbol {
@@ -104,6 +105,9 @@ struct elf {
104105
struct hlist_head *section_hash;
105106
struct hlist_head *section_name_hash;
106107
struct hlist_head *reloc_hash;
108+
109+
struct section *section_data;
110+
struct symbol *symbol_data;
107111
};
108112

109113
#define OFFSET_STRIDE_BITS 4

0 commit comments

Comments
 (0)