diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2016-12-29 10:30:28 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2016-12-29 10:30:28 (GMT) |
commit | 9f9041e11efa71cb043425cd5e89daea0247e76c (patch) | |
tree | 84d8704c291a5efef46af1e14a2aa3544dc29455 /src/format/elf | |
parent | 403a0519ec85a156a7f306b045d9cab619302473 (diff) |
Cut binary data into several areas using all the available CPUs and less memory.
Diffstat (limited to 'src/format/elf')
-rw-r--r-- | src/format/elf/elf.c | 155 |
1 files changed, 28 insertions, 127 deletions
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c index 2dd41e1..a51fe33 100644 --- a/src/format/elf/elf.c +++ b/src/format/elf/elf.c @@ -69,7 +69,7 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *); static const char *g_elf_format_get_target_machine(const GElfFormat *); /* Etend la définition des portions au sein d'un binaire. */ -static void g_elf_format_refine_portions(const GElfFormat *, GPortionLayer *); +static void g_elf_format_refine_portions(GElfFormat *); /* Fournit l'emplacement correspondant à une position physique. */ static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, vmpa2t *); @@ -244,10 +244,12 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus { GElfFormat *result; /* Structure à retourner */ GBinFormat *base; /* Version basique du format */ + GExeFormat *exe_format; /* Autre version du format */ result = g_object_new(G_TYPE_ELF_FORMAT, NULL); base = G_BIN_FORMAT(result); + exe_format = G_EXE_FORMAT(result); g_binary_format_set_content(base, content); @@ -305,7 +307,7 @@ GBinFormat *g_elf_format_new(GBinContent *content, GExeFormat *parent, GtkStatus } - if (!g_binary_format_complete_loading(base, status)) + if (!g_executable_format_complete_loading(exe_format, status)) goto gefn_error; return base; @@ -383,7 +385,6 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) /****************************************************************************** * * * Paramètres : format = informations chargées à consulter. * -* main = couche de portions principale à raffiner. * * * * Description : Etend la définition des portions au sein d'un binaire. * * * @@ -393,14 +394,13 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format) * * ******************************************************************************/ -static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer *main) +static void g_elf_format_refine_portions(GElfFormat *format) { - GPortionLayer *layer; /* Couche à mettre en place */ + GExeFormat *exe_format; /* Autre version du format */ uint16_t max; /* Décompte d'éléments traités */ - elf_phdr *sorted_phdrs; /* Liste de segments triée */ uint16_t i; /* Boucle de parcours */ off_t offset; /* Début de part de programme */ - elf_phdr *phdr; /* En-tête de programme ELF */ + elf_phdr phdr; /* En-tête de programme ELF */ uint32_t p_flags; /* Droits associés à une partie*/ const char *background; /* Fond signigicatif */ GBinPortion *new; /* Nouvelle portion définie */ @@ -409,11 +409,12 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer PortionAccessRights rights; /* Droits d'une portion */ elf_shdr strings; /* Section des descriptions */ bool has_strings; /* Section trouvée ? */ - elf_shdr *sorted_shdrs; /* Liste de sections triée */ - elf_shdr *section; /* En-tête de section ELF */ + elf_shdr shdr; /* En-tête de section ELF */ uint64_t sh_flags; /* Droits associés à une partie*/ const char *name; /* Nom trouvé ou NULL */ + exe_format = G_EXE_FORMAT(format); + /** * La copie des différents en-têtes cherche à reproduire l'inclusion native * du format : @@ -429,83 +430,35 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer * Côté segments basiques. */ - layer = g_portion_layer_new(NO_LENGTH_YET, _("Segment")); - - g_portion_layer_attach_sub(main, layer); - - /* Constitution d'une liste de travail */ - max = ELF_HDR(format, format->header, e_phnum); - sorted_phdrs = (elf_phdr *)calloc(max, sizeof(elf_phdr)); - for (i = 0; i < max; i++) { offset = ELF_HDR(format, format->header, e_phoff) + ELF_HDR(format, format->header, e_phentsize) * i; - if (!read_elf_program_header(format, offset, &sorted_phdrs[i])) - { - if (format->is_32b) - sorted_phdrs[i].phdr32.p_type = PT_NULL; - else - sorted_phdrs[i].phdr64.p_type = PT_NULL; - } - - } - - /* Tri de cette liste */ - - int sort_phdr(elf_phdr *a, elf_phdr *b) - { - uint64_t filesz_a; /* Taille de l'en-tête 'a' */ - uint64_t filesz_b; /* Taille de l'en-tête 'b' */ - int status; /* Bilan d'une comparaison */ - - filesz_a = ELF_PHDR(format, *a, p_filesz); - filesz_b = ELF_PHDR(format, *b, p_filesz); - - if (filesz_a < filesz_b) - status = 1; - - else if (filesz_a > filesz_b) - status = -1; - - else - status = 0; - - return status; - - } - - qsort(sorted_phdrs, max, sizeof(elf_phdr), (__compar_fn_t)sort_phdr); - - /* Inclusion de ces en-têtes */ - - for (i = 0; i < max; i++) - { - phdr = &sorted_phdrs[i]; + if (!read_elf_program_header(format, offset, &phdr)) + continue; - if (ELF_PHDR(format, *phdr, p_type) == PT_NULL) + if (ELF_PHDR(format, phdr, p_type) == PT_NULL) continue; - p_flags = ELF_PHDR(format, *phdr, p_flags); + p_flags = ELF_PHDR(format, phdr, p_flags); if (p_flags & PF_X) background = BPC_CODE; else if (p_flags & PF_W) background = BPC_DATA; else background = BPC_DATA_RO; - new = g_binary_portion_new(background); + init_vmpa(&addr, ELF_PHDR(format, phdr, p_offset), ELF_PHDR(format, phdr, p_vaddr)); + + new = g_binary_portion_new(background, &addr, ELF_PHDR(format, phdr, p_filesz)); snprintf(desc, MAX_PORTION_DESC, "%s \"%s\"", _("Segment"), - get_elf_program_type_desc(ELF_PHDR(format, *phdr, p_type))); + get_elf_program_type_desc(ELF_PHDR(format, phdr, p_type))); g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, ELF_PHDR(format, *phdr, p_offset), ELF_PHDR(format, *phdr, p_vaddr)); - g_binary_portion_set_values(new, &addr, ELF_PHDR(format, *phdr, p_filesz)); - rights = PAC_NONE; if (p_flags & PF_R) rights |= PAC_READ; if (p_flags & PF_W) rights |= PAC_WRITE; @@ -513,12 +466,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_rights(new, rights); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); } - free(sorted_phdrs); - /** * Inclusion des sections, si possible... */ @@ -527,64 +478,17 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer ELF_HDR(format, format->header, e_shstrndx), &strings); - layer = g_portion_layer_new(NO_LENGTH_YET, _("Section")); - - g_portion_layer_attach_sub(main, layer); - - /* Constitution d'une liste de travail */ - max = ELF_HDR(format, format->header, e_shnum); - sorted_shdrs = (elf_shdr *)calloc(max, sizeof(elf_shdr)); - - for (i = 0; i < max; i++) - { - if (!find_elf_section_by_index(format, i, &sorted_shdrs[i])) - { - if (format->is_32b) - sorted_shdrs[i].shdr32.sh_offset = 0; - else - sorted_shdrs[i].shdr64.sh_offset = 0; - } - - } - - /* Tri de cette liste */ - - int sort_shdr(elf_shdr *a, elf_shdr *b) - { - uint64_t size_a; /* Taille de l'en-tête 'a' */ - uint64_t size_b; /* Taille de l'en-tête 'b' */ - int status; /* Bilan d'une comparaison */ - - size_a = ELF_SHDR(format, *a, sh_size); - size_b = ELF_SHDR(format, *b, sh_size); - - if (size_a < size_b) - status = 1; - - else if (size_a > size_b) - status = -1; - - else - status = 0; - - return status; - - } - - qsort(sorted_shdrs, max, sizeof(elf_shdr), (__compar_fn_t)sort_shdr); - - /* Inclusion de ces en-têtes */ - for (i = 0; i < max; i++) { - section = &sorted_shdrs[i]; + if (!find_elf_section_by_index(format, i, &shdr)) + continue; - if (ELF_SHDR(format, *section, sh_offset) == 0) + if (ELF_SHDR(format, shdr, sh_offset) == 0) continue; - sh_flags = ELF_SHDR(format, *section, sh_flags); + sh_flags = ELF_SHDR(format, shdr, sh_flags); if ((sh_flags & SHF_ALLOC) == 0) continue; @@ -593,11 +497,13 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer else if (sh_flags & SHF_WRITE) background = BPC_DATA; else background = BPC_DATA_RO; - new = g_binary_portion_new(background); + init_vmpa(&addr, ELF_SHDR(format, shdr, sh_offset), ELF_SHDR(format, shdr, sh_addr)); + + new = g_binary_portion_new(background, &addr, ELF_SHDR(format, shdr, sh_size)); if (has_strings) name = extract_name_from_elf_string_section(format, &strings, - ELF_SHDR(format, *section, sh_name)); + ELF_SHDR(format, shdr, sh_name)); else name = NULL; if (name != NULL) @@ -607,9 +513,6 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_desc(new, desc); - init_vmpa(&addr, ELF_SHDR(format, *section, sh_offset), ELF_SHDR(format, *section, sh_addr)); - g_binary_portion_set_values(new, &addr, ELF_SHDR(format, *section, sh_size)); - rights = PAC_NONE; if (sh_flags & SHF_ALLOC) rights |= PAC_READ; if (sh_flags & SHF_WRITE) rights |= PAC_WRITE; @@ -617,12 +520,10 @@ static void g_elf_format_refine_portions(const GElfFormat *format, GPortionLayer g_binary_portion_set_rights(new, rights); - g_portion_layer_include(layer, new); + g_exe_format_include_portion(exe_format, new); } - free(sorted_shdrs); - } |