!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);
            !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;
 
                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))
                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);
 }
 
        char *name;
        int idx;
        bool changed, text, rodata, noinstr, init, truncate;
+       struct reloc *reloc_data;
 };
 
 struct symbol {
        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