summaryrefslogtreecommitdiff
path: root/src/format/elf/elf.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-12-29 10:30:28 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-12-29 10:30:28 (GMT)
commit9f9041e11efa71cb043425cd5e89daea0247e76c (patch)
tree84d8704c291a5efef46af1e14a2aa3544dc29455 /src/format/elf/elf.c
parent403a0519ec85a156a7f306b045d9cab619302473 (diff)
Cut binary data into several areas using all the available CPUs and less memory.
Diffstat (limited to 'src/format/elf/elf.c')
-rw-r--r--src/format/elf/elf.c155
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);
-
}