summaryrefslogtreecommitdiff
path: root/src/analysis/binary.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/binary.c')
-rw-r--r--src/analysis/binary.c385
1 files changed, 68 insertions, 317 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index c0c6e7c..9351c48 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -35,8 +35,9 @@
#include <sys/types.h>
-#include "line_code.h"
-#include "line_comment.h"
+#include "delayed.h"
+#include "line_code.h" /* TODO : supprimer ? */
+#include "line_comment.h" /* TODO : supprimer ? */
#include "line_prologue.h"
#include "prototype.h"
#include "../common/extstr.h"
@@ -79,6 +80,10 @@ struct _GOpenidaBinaryClass
{
GObjectClass parent; /* A laisser en premier */
+ /* Signaux */
+
+ void (* disassembly_done) (GOpenidaBinary *);
+
};
@@ -94,17 +99,8 @@ bin_t *map_binary_file(const char *, off_t *);
/* Construit la description d'introduction du désassemblage. */
GRenderingLine *build_binary_prologue(const char *, const uint8_t *, off_t);
-/* Procède au désassemblage basique d'un contenu binaire. */
-void disassemble_openida_binary(GOpenidaBinary *);
-
-/* Etablit les liens entres les différentes lignes de code. */
-void establish_links_in_openida_binary(const GOpenidaBinary *);
-
-/* S'assure que toutes les routines ont une taille définie. */
-void limit_all_routines_in_openida_binary(const GOpenidaBinary *);
-
-/* Cherche l'adresse de fin d'une routine. */
-vmpa_t find_best_ending_address_for_routine(GRenderingLine *, size_t, const vmpa_t *, const off_t *, size_t);
+/* Acquitte la fin d'un désasemblage différé et complet. */
+void ack_completed_disassembly(GDelayedManager *, GOpenidaBinary *, GRenderingLine *, GOpenidaBinary *);
@@ -126,6 +122,13 @@ G_DEFINE_TYPE(GOpenidaBinary, g_openida_binary, G_TYPE_OBJECT);
static void g_openida_binary_class_init(GOpenidaBinaryClass *klass)
{
+ g_signal_new("disassembly-done",
+ G_TYPE_OPENIDA_BINARY,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GOpenidaBinaryClass, disassembly_done),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
@@ -201,8 +204,6 @@ GOpenidaBinary *g_openida_binary_new_from_file(const char *filename)
g_rendering_options_show_address(result->options, MRD_GRAPH, true);
g_rendering_options_show_code(result->options, MRD_GRAPH, false);
- disassemble_openida_binary(result);
-
return result;
lbf_error:
@@ -298,6 +299,43 @@ bool g_openida_binary_save(const GOpenidaBinary *binary, xmlDocPtr xdoc, xmlXPat
/******************************************************************************
* *
+* Paramètres : binary = élément binaire à traiter. *
+* *
+* Description : Lance l'analyse d'un élément binaire chargé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_openida_binary_analyse(GOpenidaBinary *binary)
+{
+ GDelayedManager *manager; /* Gestionnaire de différés */
+ bin_part **parts; /* Parties d'élément binaire */
+ size_t parts_count; /* Nombre de ces parties */
+
+ manager = get_delayed_manager();
+
+ parts = /* !!! */get_elf_default_code_parts(binary->format, &parts_count);
+ qsort(parts, parts_count, sizeof(bin_part *), compare_bin_parts);
+
+
+
+ g_signal_connect(manager, "disassembly-completed",
+ G_CALLBACK(ack_completed_disassembly), binary);
+
+ g_delayed_manager_schedule_disassembly(manager, binary, parts, parts_count);
+
+
+
+
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : binary = élément binaire à consulter. *
* *
* Description : Fournit une description humaine d'un élément binaire. *
@@ -349,7 +387,8 @@ const char *g_openida_binary_get_filename(const GOpenidaBinary *binary)
bin_t *g_openida_binary_get_data(const GOpenidaBinary *binary, off_t *length)
{
- *length = binary->bin_length;
+ if (length != NULL)
+ *length = binary->bin_length;
return binary->bin_data;
@@ -553,9 +592,12 @@ GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data,
/******************************************************************************
* *
-* Paramètres : binary = binaire dont le contenu est à analyser. *
+* Paramètres : manager = gestionnaire des traitements en parallèle. *
+* binary = binaire dont le contenu est à analyser. *
+* lines = lignes de rendu produites par le désasemblage. *
+* user = élément binaire à l'origine du traitement. *
* *
-* Description : Procède au désassemblage basique d'un contenu binaire. *
+* Description : Acquitte la fin d'un désasemblage différé et complet. *
* *
* Retour : - *
* *
@@ -563,99 +605,25 @@ GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data,
* *
******************************************************************************/
-void disassemble_openida_binary(GOpenidaBinary *binary)
+void ack_completed_disassembly(GDelayedManager *manager, GOpenidaBinary *binary, GRenderingLine *lines, GOpenidaBinary *user)
{
-
-
- GArchInstruction *instr;
-
- GBinRoutine **routines; /* Liste des routines trouvées */
- size_t routines_count; /* Nombre de ces routines */
-
- bin_part **parts;
- size_t parts_count;
-
-
-
- GRenderingLine *line;
-
-
- off_t start;
- off_t pos;
- off_t len;
-
- uint64_t base = 0;
- vmpa_t addr = 0;
-
- size_t i;
-
- size_t k;
-
- uint64_t routine_offset; /* Point de départ de routine */
- char *routine_desc; /* Prototype d'une routine */
-
+ GRenderingLine *line; /* "Première" ligne de rendu */
GPluginModule **pglist; /* Liste de greffons */
size_t pgcount; /* Taille de cette liste */
+ size_t i; /* Boucle de parcours */
+ /* Si ce n'est pas pour nous... */
+ if (binary != user) return;
- binary->lines = build_binary_prologue(binary->filename, binary->bin_data, binary->bin_length);
-
-
- routines = get_all_exe_routines(binary->format, &routines_count);
-
-
-
-
- parts = /* !!! */get_elf_default_code_parts(binary->format, &parts_count);
- qsort(parts, parts_count, sizeof(bin_part *), compare_bin_parts);
-
- printf("PARTS COUNT :: %d\n", parts_count);
-
- for (i = 0; i < parts_count; i++)
- {
- get_bin_part_values(parts[i], &pos, &len, &base);
-
- /* Décodage des instructions */
-
- start = pos;
- pos = 0;
-
- while (pos < len)
- {
- addr = base + pos;
-
-
- instr = g_arch_processor_decode_instruction(binary->proc, &binary->bin_data[start], &pos, len, start, addr);
-
- line = g_code_line_new(addr, instr, binary->options);
- g_rendering_line_add_to_lines(&binary->lines, line);
-
- }
-
- /* Ajout des prototypes de fonctions */
-
- for (k = 0; k < routines_count; k++)
- {
- routine_offset = g_binary_routine_get_address(routines[k]);
-
- if (!(base <= routine_offset && routine_offset < (base + len))) continue;
-
- routine_desc = g_binary_routine_to_string(routines[k]);
+ binary->lines = lines;
- line = g_comment_line_new(routine_offset, routine_desc, binary->options);
- g_rendering_line_insert_into_lines(&binary->lines, line, true);
- free(routine_desc);
- }
- }
- establish_links_in_openida_binary(binary);
- limit_all_routines_in_openida_binary(binary);
- line = g_rendering_line_find_by_address(binary->lines, NULL, get_exe_entry_point(binary->format));
+ line = g_rendering_line_find_by_address(lines, NULL, get_exe_entry_point(binary->format));
if (line != NULL) g_rendering_line_add_flag(line, RLF_ENTRY_POINT);
/* Action post-désassemblage */
@@ -671,223 +639,6 @@ void disassemble_openida_binary(GOpenidaBinary *binary)
}
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = binaire dont le contenu est à lier. *
-* *
-* Description : Etablit les liens entres les différentes lignes de code. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void establish_links_in_openida_binary(const GOpenidaBinary *binary)
-{
- GBinRoutine **routines; /* Liste des routines trouvées */
- size_t routines_count; /* Nombre de ces routines */
- size_t i; /* Boucle de parcours */
- vmpa_t start; /* Adresse de départ */
- vmpa_t end; /* Adresse de fin */
- GRenderingLine *iter; /* Boucle de parcours */
- GArchInstruction *instr; /* Instruction à ausculter */
- vmpa_t addr; /* Adresse référencée */
- InstructionLinkType type; /* Type de référence */
- GRenderingLine *target; /* Ligne visée par la référence*/
-
- routines = get_all_exe_routines(binary->format, &routines_count);
-
- for (i = 0; i < routines_count; i++)
- {
- start = g_binary_routine_get_address(routines[i]);
- end = start + g_binary_routine_get_size(routines[i]);
-
- for (iter = g_rendering_line_find_by_address(binary->lines, NULL, start);
- iter != NULL;
- iter = g_rendering_line_get_next_iter(binary->lines, iter, NULL))
- {
- /* Si on sort de la zone... */
- if (get_rendering_line_address(iter) >= end) break;
-
- /* On ne traite que du code ici ! */
- if (!G_IS_CODE_LINE(iter)) continue;
-
- instr = g_code_line_get_instruction(G_CODE_LINE(iter));
- type = g_arch_instruction_get_link(instr, &addr);
-
- switch (type)
- {
- case ILT_NONE:
- break;
-
- case ILT_JUMP:
-
- target = g_rendering_line_find_by_address(binary->lines, NULL, addr);
-
- if (target != NULL)
- g_rendering_line_link_with(iter, target, type);
-
- break;
-
- case ILT_JUMP_IF_FALSE:
- break;
-
- case ILT_JUMP_IF_TRUE:
-
- target = g_rendering_line_find_by_address(binary->lines, NULL, addr);
-
- if (target != NULL)
- {
- g_rendering_line_link_with(iter, target, type);
-
- target = g_rendering_line_get_next_iter(binary->lines, iter, NULL);
- if (target != NULL)
- g_rendering_line_link_with(iter, target, ILT_JUMP_IF_FALSE);
-
- }
-
- break;
-
- case ILT_CALL:
-
- target = g_rendering_line_find_by_address(binary->lines, NULL, addr);
-
- if (target != NULL)
- g_rendering_line_link_with(iter, target, type);
-
- break;
-
- }
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : binary = binaire dont le contenu est à lier. *
-* *
-* Description : S'assure que toutes les routines ont une taille définie. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void limit_all_routines_in_openida_binary(const GOpenidaBinary *binary)
-{
- GBinRoutine **routines; /* Liste des routines trouvées */
- size_t routines_count; /* Nombre de ces routines */
- size_t i; /* Boucle de parcours */
- vmpa_t *starts; /* Adresses de départ */
- off_t *lengths; /* Tailles des routines */
- GRenderingLine *line; /* Ligne de départ / d'arrivée */
- vmpa_t start; /* Adresse de début de routine */
- vmpa_t last; /* Meilleur dernière adresse */
- GArchInstruction *instr; /* Instruction à ausculter */
- off_t length; /* Taille du code */
-
- routines = get_all_exe_routines(binary->format, &routines_count);
- if (routines_count == 0) return;
-
- qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare);
-
- starts = (vmpa_t *)calloc(routines_count, sizeof(vmpa_t));
- lengths = (off_t *)calloc(routines_count, sizeof(off_t));
-
- for (i = 0; i < routines_count; i++)
- {
- starts[i] = g_binary_routine_get_address(routines[i]);
- lengths[i] = g_binary_routine_get_size(routines[i]);
- }
-
- for (i = 0; i < routines_count; i++)
- {
- if (lengths[i] > 0) continue;
-
- start = g_binary_routine_get_address(routines[i]);
- line = g_rendering_line_find_by_address(binary->lines, NULL, start);
-
- last = find_best_ending_address_for_routine(line, i, starts, lengths, routines_count);
-
- line = g_rendering_line_find_by_address(binary->lines, NULL, last);
- line = g_rendering_line_loop_for_code(line, NULL);
-
- instr = g_code_line_get_instruction(G_CODE_LINE(line));
- g_arch_instruction_get_location(instr, NULL, &length, NULL);
-
- lengths[i] = last - start + length;
- g_binary_routine_set_size(routines[i], lengths[i]);
-
- }
-
- free(starts);
- free(lengths);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne de départ du parcours. *
-* index = indice de la routine traitée dans la liste. *
-* starts = adresse de départ des autres routines. *
-* lengths = taille des différentes routines, valides ou nulles.*
-* count = quantité de routines présentes. *
-* *
-* Description : Cherche l'adresse de fin d'une routine. *
-* *
-* Retour : Plus grande adresse de dernière instruction de routine. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-vmpa_t find_best_ending_address_for_routine(GRenderingLine *line, size_t index, const vmpa_t *starts, const off_t *lengths, size_t count)
-{
- vmpa_t result; /* Haute adresse à remonter */
- GRenderingLine *iter; /* Boucle de parcours #1 */
- vmpa_t candidate; /* Candidat potentiel */
- size_t i; /* Boucle de parcours #2 */
- GArchInstruction *instr; /* Instruction à ausculter */
-
- result = starts[index];
-
- for (iter = line; iter != NULL; iter = g_rendering_line_get_next_iter(line, iter, NULL))
- {
- if (!G_IS_CODE_LINE(iter)) continue;
-
- candidate = get_rendering_line_address(iter);
-
- /* Regarde si on n'empiète pas sur une autre routine */
-
- for (i = 0; i < count; i++)
- {
- if (i == index) continue;
-
- if (starts[i] <= candidate && candidate < (starts[i] + lengths[i]))
- break;
-
- }
-
- if (i != count) break;
- else result = candidate;
-
- /* Retour de fonction ? */
-
- instr = g_code_line_get_instruction(G_CODE_LINE(iter));
- if (g_arch_instruction_is_return(instr)) break;
-
- }
-
- return result;
+ g_signal_emit_by_name(binary, "disassembly-done");
}